@apexops/cli 0.10.0-next.5 → 0.11.0-next.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (366) hide show
  1. package/assets/capability-packs/registry.v1.json +1 -62
  2. package/assets/client-projection-metadata/copilot-cli-agent-tools.json +12 -0
  3. package/assets/client-projections/github-copilot-cli/.github/copilot/settings.json +13 -0
  4. package/assets/client-projections/github-copilot-cli/.github/instructions/apex-prompt-authoring.instructions.md +1 -1
  5. package/assets/client-projections/github-copilot-cli/.github/workflows/governance-policy-baseline.yml +101 -0
  6. package/assets/client-projections/github-copilot-cli/tools/schemas/governance-baseline.schema.json +118 -0
  7. package/assets/client-projections/github-copilot-cli/tools/scripts/collect-governance-baseline.ps1 +817 -0
  8. package/assets/config/capability-packs.v1.json +1 -32
  9. package/assets/config/governance-reference.v1.json +26379 -0
  10. package/assets/config/recipe-packs.v1.json +1 -26
  11. package/assets/config/runtime-bundle.v1.json +7 -7
  12. package/assets/config/toolchain.v1.json +35 -33
  13. package/assets/config/workflow.v1.json +103 -72
  14. package/assets/customizations/.github/agents/apex-codegen.agent.md +8 -22
  15. package/assets/customizations/.github/agents/apex-validator.agent.md +14 -20
  16. package/assets/customizations/.github/agents/apex.agent.md +108 -75
  17. package/assets/customizations/.github/copilot/settings.json +13 -0
  18. package/assets/customizations/.github/instructions/apex-prompt-authoring.instructions.md +1 -1
  19. package/assets/customizations/.github/skills/apex-architecture/SKILL.md +62 -18
  20. package/assets/customizations/.github/skills/apex-artifacts/SKILL.md +28 -6
  21. package/assets/customizations/.github/skills/apex-azure-adr/SKILL.md +3 -0
  22. package/assets/customizations/.github/skills/apex-azure-cloud-migrate/SKILL.md +3 -0
  23. package/assets/customizations/.github/skills/apex-azure-compliance/SKILL.md +3 -0
  24. package/assets/customizations/.github/skills/apex-azure-compute/SKILL.md +3 -0
  25. package/assets/customizations/.github/skills/apex-azure-cost-optimization/SKILL.md +3 -0
  26. package/assets/customizations/.github/skills/apex-azure-defaults/SKILL.md +3 -0
  27. package/assets/customizations/.github/skills/apex-azure-defaults/references/governance-effects.md +5 -3
  28. package/assets/customizations/.github/skills/apex-azure-deploy/SKILL.md +3 -0
  29. package/assets/customizations/.github/skills/apex-azure-diagnostics/SKILL.md +3 -0
  30. package/assets/customizations/.github/skills/apex-azure-governance/SKILL.md +19 -3
  31. package/assets/customizations/.github/skills/apex-azure-governance/references/evidence-interpretation.md +38 -3
  32. package/assets/customizations/.github/skills/apex-azure-kusto/SKILL.md +3 -0
  33. package/assets/customizations/.github/skills/apex-azure-prepare/SKILL.md +5 -3
  34. package/assets/customizations/.github/skills/apex-azure-quotas/SKILL.md +6 -2
  35. package/assets/customizations/.github/skills/apex-azure-quotas/references/capacity-decision-rules.md +4 -3
  36. package/assets/customizations/.github/skills/apex-azure-quotas/references/operational-checklist.md +3 -2
  37. package/assets/customizations/.github/skills/apex-azure-rbac/SKILL.md +3 -0
  38. package/assets/customizations/.github/skills/apex-azure-resources/SKILL.md +3 -0
  39. package/assets/customizations/.github/skills/apex-azure-storage/SKILL.md +3 -0
  40. package/assets/customizations/.github/skills/apex-azure-validate/SKILL.md +3 -0
  41. package/assets/customizations/.github/skills/apex-bicep-patterns/SKILL.md +3 -0
  42. package/assets/customizations/.github/skills/apex-codegen/SKILL.md +6 -2
  43. package/assets/customizations/.github/skills/apex-entra-app-registration/SKILL.md +3 -0
  44. package/assets/customizations/.github/skills/apex-mermaid/SKILL.md +3 -0
  45. package/assets/customizations/.github/skills/apex-microsoft-docs/SKILL.md +3 -0
  46. package/assets/customizations/.github/skills/apex-next/SKILL.md +99 -0
  47. package/assets/customizations/.github/skills/apex-operations/SKILL.md +46 -16
  48. package/assets/customizations/.github/skills/apex-planning/SKILL.md +48 -19
  49. package/assets/customizations/.github/skills/apex-requirements/SKILL.md +61 -26
  50. package/assets/customizations/.github/skills/apex-terraform-import/SKILL.md +3 -0
  51. package/assets/customizations/.github/skills/apex-terraform-patterns/SKILL.md +3 -0
  52. package/assets/customizations/.github/skills/apex-terraform-test/SKILL.md +3 -0
  53. package/assets/customizations/.github/skills/apex-unslop/LICENSE.txt +21 -0
  54. package/assets/customizations/.github/skills/apex-unslop/SKILL.md +94 -0
  55. package/assets/customizations/.github/skills/apex-workflow/SKILL.md +15 -5
  56. package/assets/customizations/.github/workflows/governance-policy-baseline.yml +101 -0
  57. package/assets/customizations/README.md +8 -9
  58. package/assets/customizations/manifest.json +167 -209
  59. package/assets/customizations/tools/schemas/governance-baseline.schema.json +118 -0
  60. package/assets/customizations/tools/scripts/collect-governance-baseline.ps1 +817 -0
  61. package/assets/manifest.json +423 -4241
  62. package/assets/schemas/governance-baseline.schema.json +118 -0
  63. package/dist/assets.d.ts +18 -2
  64. package/dist/assets.js +115 -35
  65. package/dist/bootstrap-wizard.d.ts +37 -0
  66. package/dist/bootstrap-wizard.js +259 -0
  67. package/dist/cli.d.ts +17 -2
  68. package/dist/cli.js +180 -63
  69. package/dist/dependency-revision.js +8 -0
  70. package/dist/errors.d.ts +6 -1
  71. package/dist/errors.js +55 -0
  72. package/dist/host-profile.d.ts +47 -0
  73. package/dist/host-profile.js +269 -0
  74. package/dist/mcp-output-schemas.d.ts +43 -0
  75. package/dist/mcp-output-schemas.js +279 -0
  76. package/dist/mcp-tool-effects.d.ts +101 -0
  77. package/dist/mcp-tool-effects.js +66 -0
  78. package/dist/mcp.d.ts +50 -3
  79. package/dist/mcp.js +800 -87
  80. package/dist/runtime-binding.d.ts +37 -0
  81. package/dist/runtime-binding.js +131 -0
  82. package/dist/service.d.ts +643 -38
  83. package/dist/service.js +4937 -662
  84. package/dist/state-transfer.js +21 -1
  85. package/dist/target-scope.d.ts +4 -0
  86. package/dist/target-scope.js +9 -0
  87. package/dist/version.d.ts +3 -1
  88. package/dist/version.js +19 -1
  89. package/dist/workflow-validators.d.ts +20 -3
  90. package/dist/workflow-validators.js +408 -67
  91. package/dist/workspace-root.d.ts +7 -0
  92. package/dist/workspace-root.js +67 -0
  93. package/package.json +11 -12
  94. package/assets/capability-packs/azure-governance-discovery/source/scripts/discover.py +0 -1189
  95. package/assets/capability-packs/azure-governance-discovery/source/scripts/render_governance.py +0 -676
  96. package/assets/client-projections/github-copilot-cli/.github/agents/apex-architect.agent.md +0 -91
  97. package/assets/client-projections/github-copilot-cli/.github/agents/apex-operator.agent.md +0 -75
  98. package/assets/client-projections/github-copilot-cli/.github/agents/apex-planner.agent.md +0 -88
  99. package/assets/client-projections/github-copilot-cli/.github/agents/apex-requirements.agent.md +0 -99
  100. package/assets/client-projections/github-copilot-cli/.github/agents/apex.agent.md +0 -88
  101. package/assets/client-projections/github-copilot-cli/.github/mcp.json +0 -65
  102. package/assets/client-projections/github-copilot-cli/.github/skills/apex-architecture/SKILL.md +0 -36
  103. package/assets/client-projections/github-copilot-cli/.github/skills/apex-artifacts/SKILL.md +0 -65
  104. package/assets/client-projections/github-copilot-cli/.github/skills/apex-artifacts/references/presentation-conventions.md +0 -52
  105. package/assets/client-projections/github-copilot-cli/.github/skills/apex-artifacts/references/reference-only-outlines.md +0 -78
  106. package/assets/client-projections/github-copilot-cli/.github/skills/apex-artifacts/templates/architecture-assessment.md +0 -35
  107. package/assets/client-projections/github-copilot-cli/.github/skills/apex-artifacts/templates/cost-estimate.md +0 -47
  108. package/assets/client-projections/github-copilot-cli/.github/skills/apex-artifacts/templates/deployment-summary.md +0 -35
  109. package/assets/client-projections/github-copilot-cli/.github/skills/apex-artifacts/templates/governance-constraints.md +0 -35
  110. package/assets/client-projections/github-copilot-cli/.github/skills/apex-artifacts/templates/implementation-plan.md +0 -43
  111. package/assets/client-projections/github-copilot-cli/.github/skills/apex-artifacts/templates/operations-runbook.md +0 -35
  112. package/assets/client-projections/github-copilot-cli/.github/skills/apex-artifacts/templates/requirements.md +0 -42
  113. package/assets/client-projections/github-copilot-cli/.github/skills/apex-artifacts/templates/resource-inventory.md +0 -29
  114. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-adr/SKILL.md +0 -52
  115. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-adr/references/decision-examples.md +0 -38
  116. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-adr/references/decision-guardrails.md +0 -36
  117. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-adr/references/decision-quality.md +0 -21
  118. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-adr/references/decision-record-fields.md +0 -57
  119. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-cloud-migrate/SKILL.md +0 -55
  120. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-cloud-migrate/references/lambda-to-functions-assessment.md +0 -29
  121. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-cloud-migrate/references/migration-readiness.md +0 -27
  122. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-cloud-migrate/references/staged-validation-handoff.md +0 -26
  123. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-cloud-migrate/references/workload-mapping.md +0 -27
  124. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-compliance/SKILL.md +0 -58
  125. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-compliance/references/compliance-finding-criteria.md +0 -63
  126. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-compliance/references/operational-checklist.md +0 -24
  127. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-compute/SKILL.md +0 -36
  128. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-compute/references/compute-selection.md +0 -26
  129. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-compute/references/pricing-evidence.md +0 -11
  130. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-compute/references/recommendation-and-scale-rules.md +0 -44
  131. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-cost-optimization/SKILL.md +0 -61
  132. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-cost-optimization/references/cost-assessment-criteria.md +0 -61
  133. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-cost-optimization/references/operational-checklist.md +0 -24
  134. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-defaults/SKILL.md +0 -59
  135. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-defaults/references/avm-binding-guidance.md +0 -29
  136. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-defaults/references/baseline-fallbacks.md +0 -53
  137. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-defaults/references/cost-monitoring.md +0 -47
  138. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-defaults/references/decision-boundaries.md +0 -19
  139. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-defaults/references/governance-effects.md +0 -28
  140. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-defaults/references/naming.md +0 -47
  141. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-defaults/references/network-planning.md +0 -47
  142. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-defaults/references/security-baseline.md +0 -40
  143. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-defaults/references/service-selection.md +0 -51
  144. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-defaults/references/tag-precedence.md +0 -31
  145. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-deploy/SKILL.md +0 -50
  146. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-deploy/references/operational-checklist.md +0 -26
  147. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-deploy/references/preview-recovery-verification.md +0 -48
  148. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-diagnostics/SKILL.md +0 -60
  149. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-diagnostics/references/diagnostic-interpretation.md +0 -42
  150. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-diagnostics/references/operational-checklist.md +0 -24
  151. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-governance/SKILL.md +0 -52
  152. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-governance/references/evidence-interpretation.md +0 -58
  153. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-governance/references/operational-checklist.md +0 -25
  154. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-kusto/SKILL.md +0 -58
  155. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-kusto/references/kql-evidence-interpretation.md +0 -41
  156. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-kusto/references/operational-checklist.md +0 -25
  157. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-prepare/SKILL.md +0 -52
  158. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-prepare/references/functions-recipe-pack.md +0 -27
  159. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-prepare/references/preparation-lineage.md +0 -36
  160. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-quotas/SKILL.md +0 -53
  161. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-quotas/references/capacity-decision-rules.md +0 -48
  162. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-quotas/references/operational-checklist.md +0 -23
  163. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-rbac/SKILL.md +0 -45
  164. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-rbac/references/assignment-intent.md +0 -39
  165. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-rbac/references/least-privilege-selection.md +0 -50
  166. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-resources/SKILL.md +0 -54
  167. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-resources/references/inventory-query-patterns.md +0 -49
  168. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-resources/references/operational-checklist.md +0 -24
  169. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-storage/SKILL.md +0 -35
  170. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-storage/references/security-and-governance.md +0 -12
  171. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-storage/references/service-auth-and-sdk-boundary.md +0 -33
  172. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-storage/references/storage-selection.md +0 -12
  173. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-validate/SKILL.md +0 -49
  174. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-validate/references/operational-checklist.md +0 -24
  175. package/assets/client-projections/github-copilot-cli/.github/skills/apex-azure-validate/references/preflight-evidence.md +0 -43
  176. package/assets/client-projections/github-copilot-cli/.github/skills/apex-bicep-patterns/SKILL.md +0 -41
  177. package/assets/client-projections/github-copilot-cli/.github/skills/apex-bicep-patterns/references/avm-and-codegen-acceptance.md +0 -11
  178. package/assets/client-projections/github-copilot-cli/.github/skills/apex-bicep-patterns/references/codegen-acceptance-checklist.md +0 -46
  179. package/assets/client-projections/github-copilot-cli/.github/skills/apex-bicep-patterns/references/compiler-and-provider-gotchas.md +0 -74
  180. package/assets/client-projections/github-copilot-cli/.github/skills/apex-bicep-patterns/references/module-interfaces-and-parameters.md +0 -56
  181. package/assets/client-projections/github-copilot-cli/.github/skills/apex-bicep-patterns/references/network-and-observability.md +0 -52
  182. package/assets/client-projections/github-copilot-cli/.github/skills/apex-codegen/SKILL.md +0 -32
  183. package/assets/client-projections/github-copilot-cli/.github/skills/apex-entra-app-registration/SKILL.md +0 -53
  184. package/assets/client-projections/github-copilot-cli/.github/skills/apex-entra-app-registration/references/capability-receipts.md +0 -21
  185. package/assets/client-projections/github-copilot-cli/.github/skills/apex-entra-app-registration/references/design-and-diagnostics.md +0 -36
  186. package/assets/client-projections/github-copilot-cli/.github/skills/apex-entra-app-registration/references/oauth-registration-model.md +0 -26
  187. package/assets/client-projections/github-copilot-cli/.github/skills/apex-entra-app-registration/references/permissions-and-credentials.md +0 -27
  188. package/assets/client-projections/github-copilot-cli/.github/skills/apex-mermaid/SKILL.md +0 -44
  189. package/assets/client-projections/github-copilot-cli/.github/skills/apex-mermaid/references/styling.md +0 -33
  190. package/assets/client-projections/github-copilot-cli/.github/skills/apex-mermaid/references/syntax.md +0 -99
  191. package/assets/client-projections/github-copilot-cli/.github/skills/apex-microsoft-docs/SKILL.md +0 -53
  192. package/assets/client-projections/github-copilot-cli/.github/skills/apex-microsoft-docs/references/research-method.md +0 -91
  193. package/assets/client-projections/github-copilot-cli/.github/skills/apex-operations/SKILL.md +0 -34
  194. package/assets/client-projections/github-copilot-cli/.github/skills/apex-planning/SKILL.md +0 -36
  195. package/assets/client-projections/github-copilot-cli/.github/skills/apex-requirements/SKILL.md +0 -46
  196. package/assets/client-projections/github-copilot-cli/.github/skills/apex-terraform-import/SKILL.md +0 -47
  197. package/assets/client-projections/github-copilot-cli/.github/skills/apex-terraform-import/references/adoption-attestation.md +0 -10
  198. package/assets/client-projections/github-copilot-cli/.github/skills/apex-terraform-import/references/import-assessment.md +0 -14
  199. package/assets/client-projections/github-copilot-cli/.github/skills/apex-terraform-import/references/import-mapping.md +0 -27
  200. package/assets/client-projections/github-copilot-cli/.github/skills/apex-terraform-import/references/mapping-and-adoption-attestation.md +0 -12
  201. package/assets/client-projections/github-copilot-cli/.github/skills/apex-terraform-patterns/SKILL.md +0 -49
  202. package/assets/client-projections/github-copilot-cli/.github/skills/apex-terraform-patterns/references/module-composition-and-refactor.md +0 -20
  203. package/assets/client-projections/github-copilot-cli/.github/skills/apex-terraform-patterns/references/module-composition-and-state-boundaries.md +0 -11
  204. package/assets/client-projections/github-copilot-cli/.github/skills/apex-terraform-patterns/references/module-locks-and-codegen-acceptance.md +0 -14
  205. package/assets/client-projections/github-copilot-cli/.github/skills/apex-terraform-patterns/references/network-and-observability.md +0 -12
  206. package/assets/client-projections/github-copilot-cli/.github/skills/apex-terraform-patterns/references/plan-and-change-assessment.md +0 -24
  207. package/assets/client-projections/github-copilot-cli/.github/skills/apex-terraform-test/SKILL.md +0 -45
  208. package/assets/client-projections/github-copilot-cli/.github/skills/apex-terraform-test/references/evidence-acceptance.md +0 -10
  209. package/assets/client-projections/github-copilot-cli/.github/skills/apex-terraform-test/references/plan-mode-and-mock-design.md +0 -12
  210. package/assets/client-projections/github-copilot-cli/.github/skills/apex-terraform-test/references/plan-mode-test-design.md +0 -23
  211. package/assets/client-projections/github-copilot-cli/.github/skills/apex-terraform-test/references/test-design.md +0 -13
  212. package/assets/client-projections/github-copilot-cli/.github/skills/apex-workflow/SKILL.md +0 -37
  213. package/assets/client-projections/github-copilot-vscode/.github/agents/apex-architect.agent.md +0 -100
  214. package/assets/client-projections/github-copilot-vscode/.github/agents/apex-codegen.agent.md +0 -62
  215. package/assets/client-projections/github-copilot-vscode/.github/agents/apex-operator.agent.md +0 -79
  216. package/assets/client-projections/github-copilot-vscode/.github/agents/apex-planner.agent.md +0 -98
  217. package/assets/client-projections/github-copilot-vscode/.github/agents/apex-requirements.agent.md +0 -108
  218. package/assets/client-projections/github-copilot-vscode/.github/agents/apex-reviewer.agent.md +0 -63
  219. package/assets/client-projections/github-copilot-vscode/.github/agents/apex-validator.agent.md +0 -61
  220. package/assets/client-projections/github-copilot-vscode/.github/agents/apex.agent.md +0 -107
  221. package/assets/client-projections/github-copilot-vscode/.github/copilot-instructions.md +0 -13
  222. package/assets/client-projections/github-copilot-vscode/.github/instructions/apex-agent-authoring.instructions.md +0 -14
  223. package/assets/client-projections/github-copilot-vscode/.github/instructions/apex-artifact-contracts.instructions.md +0 -12
  224. package/assets/client-projections/github-copilot-vscode/.github/instructions/apex-automation.instructions.md +0 -12
  225. package/assets/client-projections/github-copilot-vscode/.github/instructions/apex-azure-yaml.instructions.md +0 -12
  226. package/assets/client-projections/github-copilot-vscode/.github/instructions/apex-bicep.instructions.md +0 -12
  227. package/assets/client-projections/github-copilot-vscode/.github/instructions/apex-code-quality.instructions.md +0 -12
  228. package/assets/client-projections/github-copilot-vscode/.github/instructions/apex-context.instructions.md +0 -12
  229. package/assets/client-projections/github-copilot-vscode/.github/instructions/apex-documentation.instructions.md +0 -12
  230. package/assets/client-projections/github-copilot-vscode/.github/instructions/apex-governance.instructions.md +0 -12
  231. package/assets/client-projections/github-copilot-vscode/.github/instructions/apex-instruction-authoring.instructions.md +0 -12
  232. package/assets/client-projections/github-copilot-vscode/.github/instructions/apex-javascript.instructions.md +0 -11
  233. package/assets/client-projections/github-copilot-vscode/.github/instructions/apex-json.instructions.md +0 -11
  234. package/assets/client-projections/github-copilot-vscode/.github/instructions/apex-markdown.instructions.md +0 -13
  235. package/assets/client-projections/github-copilot-vscode/.github/instructions/apex-powershell.instructions.md +0 -11
  236. package/assets/client-projections/github-copilot-vscode/.github/instructions/apex-prompt-authoring.instructions.md +0 -12
  237. package/assets/client-projections/github-copilot-vscode/.github/instructions/apex-python.instructions.md +0 -11
  238. package/assets/client-projections/github-copilot-vscode/.github/instructions/apex-safe-file-edits.instructions.md +0 -11
  239. package/assets/client-projections/github-copilot-vscode/.github/instructions/apex-safe-shell.instructions.md +0 -11
  240. package/assets/client-projections/github-copilot-vscode/.github/instructions/apex-shell.instructions.md +0 -11
  241. package/assets/client-projections/github-copilot-vscode/.github/instructions/apex-skill-authoring.instructions.md +0 -13
  242. package/assets/client-projections/github-copilot-vscode/.github/instructions/apex-terraform.instructions.md +0 -12
  243. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-architecture/SKILL.md +0 -36
  244. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-artifacts/SKILL.md +0 -65
  245. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-artifacts/references/presentation-conventions.md +0 -52
  246. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-artifacts/references/reference-only-outlines.md +0 -78
  247. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-artifacts/templates/architecture-assessment.md +0 -35
  248. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-artifacts/templates/cost-estimate.md +0 -47
  249. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-artifacts/templates/deployment-summary.md +0 -35
  250. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-artifacts/templates/governance-constraints.md +0 -35
  251. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-artifacts/templates/implementation-plan.md +0 -43
  252. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-artifacts/templates/operations-runbook.md +0 -35
  253. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-artifacts/templates/requirements.md +0 -42
  254. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-artifacts/templates/resource-inventory.md +0 -29
  255. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-adr/SKILL.md +0 -52
  256. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-adr/references/decision-examples.md +0 -38
  257. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-adr/references/decision-guardrails.md +0 -36
  258. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-adr/references/decision-quality.md +0 -21
  259. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-adr/references/decision-record-fields.md +0 -57
  260. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-cloud-migrate/SKILL.md +0 -55
  261. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-cloud-migrate/references/lambda-to-functions-assessment.md +0 -29
  262. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-cloud-migrate/references/migration-readiness.md +0 -27
  263. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-cloud-migrate/references/staged-validation-handoff.md +0 -26
  264. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-cloud-migrate/references/workload-mapping.md +0 -27
  265. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-compliance/SKILL.md +0 -58
  266. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-compliance/references/compliance-finding-criteria.md +0 -63
  267. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-compliance/references/operational-checklist.md +0 -24
  268. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-compute/SKILL.md +0 -36
  269. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-compute/references/compute-selection.md +0 -26
  270. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-compute/references/pricing-evidence.md +0 -11
  271. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-compute/references/recommendation-and-scale-rules.md +0 -44
  272. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-cost-optimization/SKILL.md +0 -61
  273. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-cost-optimization/references/cost-assessment-criteria.md +0 -61
  274. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-cost-optimization/references/operational-checklist.md +0 -24
  275. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-defaults/SKILL.md +0 -59
  276. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-defaults/references/avm-binding-guidance.md +0 -29
  277. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-defaults/references/baseline-fallbacks.md +0 -53
  278. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-defaults/references/cost-monitoring.md +0 -47
  279. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-defaults/references/decision-boundaries.md +0 -19
  280. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-defaults/references/governance-effects.md +0 -28
  281. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-defaults/references/naming.md +0 -47
  282. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-defaults/references/network-planning.md +0 -47
  283. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-defaults/references/security-baseline.md +0 -40
  284. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-defaults/references/service-selection.md +0 -51
  285. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-defaults/references/tag-precedence.md +0 -31
  286. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-deploy/SKILL.md +0 -50
  287. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-deploy/references/operational-checklist.md +0 -26
  288. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-deploy/references/preview-recovery-verification.md +0 -48
  289. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-diagnostics/SKILL.md +0 -60
  290. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-diagnostics/references/diagnostic-interpretation.md +0 -42
  291. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-diagnostics/references/operational-checklist.md +0 -24
  292. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-governance/SKILL.md +0 -52
  293. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-governance/references/evidence-interpretation.md +0 -58
  294. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-governance/references/operational-checklist.md +0 -25
  295. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-kusto/SKILL.md +0 -58
  296. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-kusto/references/kql-evidence-interpretation.md +0 -41
  297. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-kusto/references/operational-checklist.md +0 -25
  298. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-prepare/SKILL.md +0 -52
  299. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-prepare/references/functions-recipe-pack.md +0 -27
  300. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-prepare/references/preparation-lineage.md +0 -36
  301. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-quotas/SKILL.md +0 -53
  302. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-quotas/references/capacity-decision-rules.md +0 -48
  303. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-quotas/references/operational-checklist.md +0 -23
  304. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-rbac/SKILL.md +0 -45
  305. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-rbac/references/assignment-intent.md +0 -39
  306. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-rbac/references/least-privilege-selection.md +0 -50
  307. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-resources/SKILL.md +0 -54
  308. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-resources/references/inventory-query-patterns.md +0 -49
  309. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-resources/references/operational-checklist.md +0 -24
  310. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-storage/SKILL.md +0 -35
  311. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-storage/references/security-and-governance.md +0 -12
  312. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-storage/references/service-auth-and-sdk-boundary.md +0 -33
  313. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-storage/references/storage-selection.md +0 -12
  314. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-validate/SKILL.md +0 -49
  315. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-validate/references/operational-checklist.md +0 -24
  316. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-azure-validate/references/preflight-evidence.md +0 -43
  317. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-bicep-patterns/SKILL.md +0 -41
  318. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-bicep-patterns/references/avm-and-codegen-acceptance.md +0 -11
  319. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-bicep-patterns/references/codegen-acceptance-checklist.md +0 -46
  320. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-bicep-patterns/references/compiler-and-provider-gotchas.md +0 -74
  321. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-bicep-patterns/references/module-interfaces-and-parameters.md +0 -56
  322. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-bicep-patterns/references/network-and-observability.md +0 -52
  323. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-codegen/SKILL.md +0 -32
  324. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-entra-app-registration/SKILL.md +0 -53
  325. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-entra-app-registration/references/capability-receipts.md +0 -21
  326. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-entra-app-registration/references/design-and-diagnostics.md +0 -36
  327. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-entra-app-registration/references/oauth-registration-model.md +0 -26
  328. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-entra-app-registration/references/permissions-and-credentials.md +0 -27
  329. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-mermaid/SKILL.md +0 -44
  330. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-mermaid/references/styling.md +0 -33
  331. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-mermaid/references/syntax.md +0 -99
  332. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-microsoft-docs/SKILL.md +0 -53
  333. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-microsoft-docs/references/research-method.md +0 -91
  334. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-operations/SKILL.md +0 -34
  335. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-planning/SKILL.md +0 -36
  336. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-requirements/SKILL.md +0 -46
  337. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-terraform-import/SKILL.md +0 -47
  338. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-terraform-import/references/adoption-attestation.md +0 -10
  339. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-terraform-import/references/import-assessment.md +0 -14
  340. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-terraform-import/references/import-mapping.md +0 -27
  341. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-terraform-import/references/mapping-and-adoption-attestation.md +0 -12
  342. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-terraform-patterns/SKILL.md +0 -49
  343. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-terraform-patterns/references/module-composition-and-refactor.md +0 -20
  344. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-terraform-patterns/references/module-composition-and-state-boundaries.md +0 -11
  345. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-terraform-patterns/references/module-locks-and-codegen-acceptance.md +0 -14
  346. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-terraform-patterns/references/network-and-observability.md +0 -12
  347. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-terraform-patterns/references/plan-and-change-assessment.md +0 -24
  348. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-terraform-test/SKILL.md +0 -45
  349. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-terraform-test/references/evidence-acceptance.md +0 -10
  350. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-terraform-test/references/plan-mode-and-mock-design.md +0 -12
  351. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-terraform-test/references/plan-mode-test-design.md +0 -23
  352. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-terraform-test/references/test-design.md +0 -13
  353. package/assets/client-projections/github-copilot-vscode/.github/skills/apex-workflow/SKILL.md +0 -37
  354. package/assets/client-projections/github-copilot-vscode/.vscode/mcp.json +0 -29
  355. package/assets/customizations/.github/agents/apex-architect.agent.md +0 -93
  356. package/assets/customizations/.github/agents/apex-operator.agent.md +0 -72
  357. package/assets/customizations/.github/agents/apex-planner.agent.md +0 -91
  358. package/assets/customizations/.github/agents/apex-requirements.agent.md +0 -101
  359. package/assets/customizations/.github/agents/apex-reviewer.agent.md +0 -60
  360. package/assets/customizations/.github/mcp.json +0 -65
  361. package/assets/customizations/.github/skills/apex-azure-prepare/references/functions-recipe-pack.md +0 -27
  362. package/assets/customizations/.vscode/mcp.json +0 -29
  363. package/dist/azure-mcp-environment.d.ts +0 -2
  364. package/dist/azure-mcp-environment.js +0 -7
  365. package/dist/azure-mcp.d.ts +0 -2
  366. package/dist/azure-mcp.js +0 -21
@@ -1,676 +0,0 @@
1
- #!/usr/bin/env python3
2
- # ruff: noqa: E501
3
- """Shared governance preview renderer.
4
-
5
- Extracted from discover.py so both live discovery and cached-baseline
6
- rendering use the same artifact generator. This module has NO Azure
7
- dependencies — it only reads an in-memory governance-constraints-v1
8
- envelope and writes Markdown.
9
- """
10
- from __future__ import annotations
11
-
12
- import hashlib
13
- import json
14
- import re
15
- from datetime import datetime, timezone
16
- from pathlib import Path
17
- from typing import Any
18
-
19
- # --------------------------------------------------------------------------- #
20
- # Shared L0 envelope helpers #
21
- # #
22
- # These are the canonical implementations consumed by BOTH discover.py #
23
- # (live path) and render_cached_governance.py (cached baseline path). The #
24
- # `completeness_signature` MUST be byte-identical for the same upstream #
25
- # findings set across both paths — that invariant is the foundation of the #
26
- # Phase 4 resume short-circuit + Phase 8 challenger guard, and is regression #
27
- # tested in `test_signature_parity.py`. #
28
- # --------------------------------------------------------------------------- #
29
-
30
- # L0 envelope: staleness threshold (days). Downstream consumers (Planner,
31
- # CodeGen, Deploy) treat envelopes older than this as STALE and refuse to
32
- # proceed without a fresh `--refresh` discovery.
33
- DEFAULT_TTL_DAYS = 7
34
-
35
- # API versions emitted into discovery_metadata.api_versions. Keep in sync
36
- # with the ARM REST calls in discover.py — these constants are the single
37
- # source of truth for both the live path and any cached-baseline synthesis
38
- # that needs to claim the version it was originally collected against.
39
- API_ASSIGNMENTS = "2022-06-01"
40
- API_DEFINITIONS = "2021-06-01"
41
- API_EXEMPTIONS = "2022-07-01-preview"
42
-
43
-
44
- def _completeness_signature(findings: list[dict[str, Any]]) -> str:
45
- """Return a deterministic sha256 over the stable-sorted policy tuples.
46
-
47
- The signature is the L0 attestation used by downstream consumers
48
- (Planner, CodeGen, Deploy) to detect that a constraints file has
49
- drifted from the snapshot they validated against. Algorithm:
50
-
51
- 1. Build `(policy_id, effect, scope, params)` tuples for each finding.
52
- 2. Sort by `policy_id`.
53
- 3. Serialise each tuple as a compact JSON object with sorted keys.
54
- 4. Join with `\\n` and sha256.
55
- """
56
- tuples: list[dict[str, Any]] = []
57
- for f in findings:
58
- tuples.append(
59
- {
60
- "policy_id": f.get("policy_id") or "",
61
- "effect": f.get("effect") or "",
62
- "scope": f.get("scope") or "",
63
- "params": f.get("assignment_parameters") or {},
64
- }
65
- )
66
- tuples.sort(key=lambda t: t["policy_id"])
67
- serialized = "\n".join(json.dumps(t, sort_keys=True, separators=(",", ":")) for t in tuples)
68
- return "sha256:" + hashlib.sha256(serialized.encode("utf-8")).hexdigest()
69
-
70
-
71
- def _extract_management_groups(kept_assignments: list[dict[str, Any]]) -> list[str]:
72
- """Return MG ancestry referenced by kept assignment scopes (ordered)."""
73
- seen: dict[str, None] = {}
74
- for a in kept_assignments:
75
- scope = ((a.get("properties") or {}).get("scope") or "").lower()
76
- marker = "/providers/microsoft.management/managementgroups/"
77
- if marker not in scope:
78
- continue
79
- mg = scope.split(marker, 1)[1].split("/", 1)[0]
80
- if mg and mg not in seen:
81
- seen[mg] = None
82
- return list(seen.keys())
83
-
84
-
85
- def _build_discovery_metadata(
86
- *,
87
- findings: list[dict[str, Any]],
88
- subscription_id: str,
89
- management_groups: list[str],
90
- page_counts: dict[str, int],
91
- discovered_at: str,
92
- discovery_status: str = "COMPLETE",
93
- ttl_days: int = DEFAULT_TTL_DAYS,
94
- source: str = "live", # noqa: ARG001 — reserved for future per-source attestation; envelope-level `source` is the consumer-facing field
95
- api_versions: dict[str, str] | None = None,
96
- ) -> dict[str, Any]:
97
- """Compose the L0 `discovery_metadata` envelope.
98
-
99
- Used by both discover.py (live path, `source="live"`) and the cached
100
- renderer (`source="github-actions-baseline"`). The returned dict is
101
- byte-for-byte deterministic given the same inputs — the parity test
102
- asserts this across both call sites.
103
-
104
- `source` is currently informational; it is parameterised so future
105
- revisions can record per-attestation provenance without changing
106
- the helper signature. The envelope's top-level `source` field is
107
- what consumers actually read today.
108
- """
109
- return {
110
- "discovery_status": discovery_status,
111
- "discovered_at": discovered_at,
112
- "scope": {
113
- "subscription_id": subscription_id,
114
- "management_groups": list(management_groups),
115
- },
116
- "api_versions": dict(
117
- api_versions
118
- or {
119
- "policyAssignments": API_ASSIGNMENTS,
120
- "policyDefinitions": API_DEFINITIONS,
121
- "policyExemptions": API_EXEMPTIONS,
122
- }
123
- ),
124
- "page_counts": dict(page_counts),
125
- "completeness_signature": _completeness_signature(findings),
126
- "ttl_days": ttl_days,
127
- }
128
-
129
-
130
- def _utc_now_iso() -> str:
131
- """Return the current UTC instant in the ISO-8601 form used by discover.py."""
132
- return datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ")
133
-
134
-
135
- # --------------------------------------------------------------------------- #
136
- # Preview renderer (Markdown generation) #
137
- # --------------------------------------------------------------------------- #
138
-
139
-
140
- def _infer_project_from_path(out_path: Path) -> str:
141
- """Infer project name from the output path (e.g. agent-output/test/04-...).
142
-
143
- Falls back to 'unknown' if the path doesn't match the expected structure.
144
- """
145
- # Expect: .../agent-output/{project}/04-governance-constraints.json
146
- parts = out_path.parts
147
- for i, p in enumerate(parts):
148
- if p == "agent-output" and i + 1 < len(parts):
149
- return parts[i + 1]
150
- return "unknown"
151
-
152
-
153
- def _split_tags(tags_required: list[dict[str, Any]]) -> tuple[list[dict[str, Any]], list[dict[str, Any]]]:
154
- """Split tags into resolved and unresolved lists.
155
-
156
- Resolved tags have actual key names (e.g. 'Environment').
157
- Unresolved tags carry '[unresolved: ...]' markers from the collector.
158
- """
159
- resolved = []
160
- unresolved = []
161
- for t in tags_required:
162
- name = t.get("name", "")
163
- if t.get("unresolved") or name.startswith("[unresolved"):
164
- # Try to extract parameter-based tag names from assignment_parameters
165
- params = t.get("assignment_parameters", {})
166
- tag_params = {k: v for k, v in params.items() if k.startswith("tagName") and isinstance(v, str)}
167
- if tag_params:
168
- for _key, tag_name in sorted(tag_params.items()):
169
- resolved.append({"name": tag_name, **{k: v for k, v in t.items() if k != "name"}})
170
- else:
171
- unresolved.append(t)
172
- else:
173
- resolved.append(t)
174
- return resolved, unresolved
175
-
176
-
177
- def _extract_constraint_value(finding: dict[str, Any]) -> str | None:
178
- """Extract the actual constraint value from assignment_parameters or required_value.
179
-
180
- Returns a human-readable string summarising the constraint, or None.
181
- """
182
- # Prefer explicit required_value if present (including boolean False)
183
- rv = finding.get("required_value")
184
- if rv is not None and rv != "":
185
- if isinstance(rv, bool):
186
- return str(rv).lower()
187
- if isinstance(rv, list):
188
- return ", ".join(str(v) for v in rv[:20])
189
- return str(rv)
190
-
191
- params = finding.get("assignment_parameters") or {}
192
- for pname, pval in params.items():
193
- # Skip effect overrides: "effect", "Effect", "*MonitoringEffect", "*AppMonitoringEffect", etc.
194
- if pname.lower().endswith("effect"):
195
- continue
196
- if isinstance(pval, list) and pval:
197
- # Truncate to 20 items for readability
198
- items = [str(v) for v in pval[:20]]
199
- suffix = f" … +{len(pval) - 20} more" if len(pval) > 20 else ""
200
- return ", ".join(items) + suffix
201
- if isinstance(pval, (str, int, float, bool)) and pval not in (None, ""):
202
- return str(pval)
203
- return None
204
-
205
-
206
- def _dedup_blockers(blockers: list[dict[str, Any]]) -> list[dict[str, Any]]:
207
- """Deduplicate blockers that share policy semantics across scopes.
208
-
209
- Returns a list of representative blockers with a 'scopes' list
210
- and merged assignment_parameters from all instances.
211
- """
212
- from collections import OrderedDict
213
- groups: OrderedDict[tuple[str, str, str], list[dict[str, Any]]] = OrderedDict()
214
- for b in blockers:
215
- key = (
216
- b.get("display_name", ""),
217
- b.get("policy_id", ""),
218
- json.dumps(b.get("assignment_parameters") or {}, sort_keys=True, separators=(",", ":")),
219
- )
220
- groups.setdefault(key, []).append(b)
221
-
222
- deduped: list[dict[str, Any]] = []
223
- for _key, items in groups.items():
224
- rep = dict(items[0]) # shallow copy of first instance
225
- rep["_scopes"] = [it.get("scope", "") for it in items]
226
- # Merge assignment_parameters from all instances (first non-empty wins per key)
227
- merged_params: dict[str, Any] = {}
228
- for it in items:
229
- for k, v in (it.get("assignment_parameters") or {}).items():
230
- if k not in merged_params and v is not None and v != "":
231
- merged_params[k] = v
232
- if merged_params:
233
- rep["assignment_parameters"] = merged_params
234
- deduped.append(rep)
235
- return deduped
236
-
237
-
238
- def extract_arch_resources(arch_path: str | Path) -> list[dict[str, str]]:
239
- """Extract Azure resource types from 02-architecture-assessment.md.
240
-
241
- Scans for ARM resource type patterns (Microsoft.{Provider}/{Type}) and
242
- returns a list of {name, arm_type} dicts. Used to pre-populate
243
- policy→resource mapping in preview.md.
244
- """
245
- arch_path = Path(arch_path)
246
- if not arch_path.exists():
247
- return []
248
- text = arch_path.read_text(errors="replace")
249
- # Match ARM types like Microsoft.Compute/virtualMachines
250
- arm_pattern = re.compile(r"Microsoft\.\w+/\w+(?:/\w+)?")
251
- types_found = sorted(set(arm_pattern.findall(text)))
252
- # Also extract resource names from Mermaid diagrams or SKU tables
253
- # Pattern: common name labels like "vm-iis-01", "sql-...", "vnet-..."
254
- name_pattern = re.compile(r"(?:vm|sql|vnet|kv|st|app|pip|lb|nsg|nic|pe|natgw|log|acr|aks)-[\w-]+", re.IGNORECASE)
255
- names_found = sorted(set(name_pattern.findall(text)))
256
- resources: list[dict[str, str]] = []
257
- for t in types_found:
258
- resources.append({"arm_type": t, "name": t.split("/")[-1]})
259
- for n in names_found:
260
- if not any(r["name"] == n for r in resources):
261
- resources.append({"arm_type": "", "name": n})
262
- return resources
263
-
264
-
265
- def emit_preview_md(envelope: dict[str, Any], out_path: Path, arch_resources: list[dict[str, str]] | None = None) -> Path | None:
266
- """Write a sibling `.preview.md` with H2 structure matching the template.
267
-
268
- The agent copies this to `04-governance-constraints.md` and annotates
269
- placeholder sections only — avoiding the slow mega-patch generation.
270
-
271
- If `arch_resources` is provided (from `--arch`), the preview includes a
272
- pre-populated policy→architecture resource mapping table under
273
- "Plan Adaptations → Architectural Changes".
274
- """
275
- preview_path = out_path.with_suffix(".preview.md")
276
- project = envelope.get("project") or _infer_project_from_path(out_path)
277
- summary = envelope.get("discovery_summary", {})
278
- findings = envelope.get("findings", [])
279
- tags_required = envelope.get("tags_required", [])
280
- discovered_at = envelope.get("discovered_at", "")
281
- has_arch = arch_resources is not None and len(arch_resources) > 0
282
-
283
- # Normalize null property paths to "" (schema requires string, not null)
284
- for f in findings:
285
- if f.get("azurePropertyPath") is None:
286
- f["azurePropertyPath"] = ""
287
- if f.get("bicepPropertyPath") is None:
288
- f["bicepPropertyPath"] = ""
289
-
290
- # Deduplicate identical findings (same display_name + scope + policy_id) that arise
291
- # when the same policy is inherited at multiple MG levels with identical parameters.
292
- _seen_keys: set[tuple[str, ...]] = set()
293
- deduped_findings: list[dict[str, Any]] = []
294
- for f in findings:
295
- key = (
296
- f.get("display_name", ""),
297
- f.get("scope", ""),
298
- f.get("policy_id", ""),
299
- json.dumps(f.get("assignment_parameters") or {}, sort_keys=True, separators=(",", ":")),
300
- )
301
- if key not in _seen_keys:
302
- _seen_keys.add(key)
303
- deduped_findings.append(f)
304
- findings = deduped_findings
305
-
306
- blockers = [f for f in findings if f.get("classification") == "blocker"]
307
- auto_remediate = [f for f in findings if f.get("classification") == "auto-remediate"]
308
- # Group by category for security/network/cost sections
309
- by_category: dict[str, list[dict[str, Any]]] = {}
310
- for f in findings:
311
- cat = (f.get("category") or "Uncategorized").strip()
312
- by_category.setdefault(cat, []).append(f)
313
-
314
- # Pre-build security list (with keyword expansion) so Discovery Source count is accurate.
315
- _security_keywords = {"SFI-", "Safe Secrets", "Key Vault", "Purge Protection", "TLS", "HTTPS", "SSL"}
316
- security: list[dict[str, Any]] = list(by_category.get("Security", []))
317
- for _f in findings:
318
- if _f not in security and any(kw in (_f.get("display_name") or "") for kw in _security_keywords):
319
- security.append(_f)
320
-
321
- lines: list[str] = []
322
- a = lines.append
323
-
324
- # Header + badge row
325
- a(f"# 🛡️ Governance Constraints - {project}\n")
326
- a("![Step](https://img.shields.io/badge/Step-3.5-blue?style=for-the-badge)")
327
- a("![Status](https://img.shields.io/badge/Status-Discovered-green?style=for-the-badge)")
328
- a("![Agent](https://img.shields.io/badge/Agent-04g--Governance-purple?style=for-the-badge)\n")
329
-
330
- # TOC
331
- a("<details open>")
332
- a("<summary><strong>📑 Governance Contents</strong></summary>\n")
333
- a("- [🔍 Discovery Source](#-discovery-source)")
334
- a("- [📋 Azure Policy Compliance](#-azure-policy-compliance)")
335
- a("- [🔄 Plan Adaptations Based on Policies](#-plan-adaptations-based-on-policies)")
336
- a("- [🚫 Deployment Blockers](#-deployment-blockers)")
337
- a("- [🏷️ Required Tags](#-required-tags)")
338
- a("- [🔐 Security Policies](#-security-policies)")
339
- a("- [💰 Cost Policies](#-cost-policies)")
340
- a("- [🌐 Network Policies](#-network-policies)")
341
- a("- [📜 Compliance Frameworks](#-compliance-frameworks)")
342
- a("- [References](#references)\n")
343
- a("</details>\n")
344
-
345
- a(f"> Generated by 04g-Governance agent | {discovered_at}\n")
346
-
347
- # Cross-nav
348
- a("| ⬅️ Previous | 📑 Index | Next ➡️ |")
349
- a("| --- | --- | --- |")
350
- a("| [02-architecture-assessment.md](02-architecture-assessment.md) | [README](README.md) | [04-implementation-plan.md](04-implementation-plan.md) |\n")
351
-
352
- # Discovery Source
353
- a("## 🔍 Discovery Source\n")
354
- a("| Query | Results | Timestamp |")
355
- a("| --- | --- | --- |")
356
- a(f"| Policy Assignments | {summary.get('assignment_kept', 0)} policies discovered | {discovered_at} |")
357
- a(f"| Tag Policies | {len(tags_required)} tags required | {discovered_at} |")
358
- a(f"| Security Policies | {len(security)} constraints | {discovered_at} |\n")
359
- is_cached = envelope.get("source") == "cached_baseline" or envelope.get("cached_baseline", False)
360
- discovery_method = "Cached governance baseline (governance-policy-baseline.json)" if is_cached else "Azure Policy REST API (discover.py)"
361
- a(f"**Discovery Method**: {discovery_method}")
362
- a(f"**Subscription**: {envelope.get('subscription_id', 'unknown')}")
363
- a(f"**Scope**: Subscription + management-group inherited\n")
364
- if blockers:
365
- a(f"> ⚠️ **{len(blockers)} deployment blocker(s)** detected. Review the [Deployment Blockers](#-deployment-blockers) section before proceeding to IaC planning.\n")
366
-
367
- # Policy Definition Analysis table
368
- a("### Policy Definition Analysis\n")
369
- a("| Policy Display Name | Assignment Scope | Effect | Classification | Category | Bicep Property Path | Required Value |")
370
- a("| --- | --- | --- | --- | --- | --- | --- |")
371
- for f in findings:
372
- constraint = _extract_constraint_value(f) or ""
373
- bpp = f.get("bicepPropertyPath", "")
374
- # For policies that only check resource type (bpp == "type"), clarify
375
- if bpp == "type":
376
- bpp = "type (resource-type constraint)"
377
- a(f"| {f.get('display_name', '')} | {f.get('scope', '')} | {f.get('effect', '')} "
378
- f"| {f.get('classification', '')} | {f.get('category', '')} "
379
- f"| {bpp} | {constraint} |")
380
- a("")
381
-
382
- # Azure Policy Compliance
383
- a("## 📋 Azure Policy Compliance\n")
384
- if not has_arch:
385
- a("> **Note**: No architecture assessment provided. IaC impact annotations will be populated during Step 4 (IaC Planning).\n")
386
- a("| Category | Constraint | Implementation | Status |")
387
- a("| --- | --- | --- | --- |")
388
- # Implementation column is descriptive (not prescriptive): when an
389
- # architecture is provided we redirect the reader to the structured JSON
390
- # rather than emit an annotation placeholder the agent has to fill in.
391
- # See plan-optimiseGovernanceAgent.prompt.md Phase 2.
392
- for cat, items in sorted(by_category.items()):
393
- for f in items:
394
- cls = f.get("classification", "")
395
- if cls == "blocker":
396
- status_icon = "❌"
397
- impl = (
398
- "Blocked — must comply before deployment"
399
- if not has_arch
400
- else "See JSON findings[] for structured value."
401
- )
402
- elif cls == "auto-remediate":
403
- status_icon = "✅"
404
- impl = (
405
- "Auto-applied by Azure Policy"
406
- if not has_arch
407
- else "See JSON findings[] for structured value."
408
- )
409
- else:
410
- status_icon = "⚠️"
411
- impl = (
412
- "Audit only — no enforcement"
413
- if not has_arch
414
- else "See JSON findings[] for structured value."
415
- )
416
- a(f"| {cat} | {f.get('display_name', '')} | {impl} | {status_icon} |")
417
- a("")
418
-
419
- # Plan Adaptations
420
- a("## 🔄 Plan Adaptations Based on Policies\n")
421
-
422
- # Architectural Changes — pre-populated policy→resource mapping
423
- a("### Architectural Changes\n")
424
- if blockers and arch_resources:
425
- a("| Original Design | Blocking Policy | Effect | Target Resource Types | Adaptation Applied |")
426
- a("| --- | --- | --- | --- | --- |")
427
- # Descriptive (not prescriptive) per-row text — the renderer no longer
428
- # claims annotation work the agent has not done. See plan-
429
- # optimiseGovernanceAgent.prompt.md Phase 2 for the rationale.
430
- for f in blockers:
431
- f_types = set(f.get("resource_types", []))
432
- matched = [r for r in arch_resources if r.get("arm_type", "") in f_types]
433
- adaptation_note = (
434
- "Deny effect — Step 4 must map to an explicit IaC control "
435
- "or document an exception."
436
- )
437
- if matched:
438
- for r in matched:
439
- a(f"| {r.get('name', '')} ({r.get('arm_type', '')}) "
440
- f"| {f.get('display_name', '')} | {f.get('effect', '')} "
441
- f"| {', '.join(f_types)} | {adaptation_note} |")
442
- else:
443
- a(f"| Cross-check against architecture resource map (Step 4 input). "
444
- f"| {f.get('display_name', '')} | {f.get('effect', '')} "
445
- f"| {', '.join(f_types)} | {adaptation_note} |")
446
- elif blockers:
447
- a("| Original Design | Blocking Policy | Effect | Adaptation Applied |")
448
- a("| --- | --- | --- | --- |")
449
- for f in blockers:
450
- a(f"| No architecture target | {f.get('display_name', '')} | {f.get('effect', '')} "
451
- f"| Review at Step 4 IaC Planning |")
452
- else:
453
- a("✅ Original architecture complies with all discovered policies.\n")
454
- a("")
455
-
456
- a("### Auto-Applied Resources\n")
457
- dine_findings = [f for f in findings if f.get("effect") == "deployIfNotExists"]
458
- if dine_findings:
459
- a("| Policy | Effect | Auto-Applied Resource |")
460
- a("| --- | --- | --- |")
461
- # DeployIfNotExists effects are platform-driven — the descriptor is
462
- # the same whether or not architecture context is available, so we
463
- # drop the conditional placeholder.
464
- for f in dine_findings:
465
- a(f"| {f.get('display_name', '')} | DeployIfNotExists | Auto-deployed by Azure Policy |")
466
- else:
467
- a("✅ No additional resources will be auto-deployed.\n")
468
- a("")
469
-
470
- a("### Auto-Modified Configurations\n")
471
- modify_findings = [f for f in findings if f.get("effect") == "modify"]
472
- if modify_findings:
473
- a("| Policy | Effect | Auto-Applied Change |")
474
- a("| --- | --- | --- |")
475
- # Modify effects are platform-driven (see DINE comment above).
476
- for f in modify_findings:
477
- a(f"| {f.get('display_name', '')} | Modify | Auto-modified by Azure Policy |")
478
- else:
479
- a("✅ No auto-modifications expected.\n")
480
- a("")
481
-
482
- # Deployment Blockers (deduplicated by display_name)
483
- a("## 🚫 Deployment Blockers\n")
484
- if not blockers:
485
- a("✅ No deployment blockers detected.\n")
486
- else:
487
- deduped = _dedup_blockers(blockers)
488
- a(f"> **{len(blockers)}** blocker finding(s) from **{len(deduped)}** unique policies (duplicates from multi-scope inheritance are consolidated below).\n")
489
- for f in deduped:
490
- a(f"### {f.get('display_name', 'Unknown Policy')}\n")
491
- a(f"- **Policy ID**: `{f.get('policy_id', '')}`")
492
- a(f"- **Effect**: {f.get('effect', '')}")
493
- scopes = f.get("_scopes", [f.get("scope", "")])
494
- if len(scopes) > 1:
495
- a(f"- **Scopes** ({len(scopes)} assignments):")
496
- for s in scopes:
497
- a(f" - `{s}`")
498
- else:
499
- a(f"- **Scope**: {scopes[0]}")
500
- a(f"- **Category**: {f.get('category', '')}")
501
- bpp = f.get("bicepPropertyPath", "")
502
- if bpp == "type":
503
- bpp = "type (resource-type constraint — enforced at type level, not a specific property)"
504
- a(f"- **Bicep Property Path**: `{bpp}`")
505
- constraint = _extract_constraint_value(f)
506
- a(f"- **Required Value**: {constraint or 'N/A — parameter values not available in cached baseline; run `--refresh` for live lookup'}")
507
- a("")
508
- # Resolution guidance is uniform whether or not architecture
509
- # context is present — the per-finding structured fields above
510
- # already carry everything the Step 4 planner needs. The prior
511
- # `<!-- AGENT: annotate resolution options below -->` block was
512
- # dropped in plan-optimiseGovernanceAgent.prompt.md Phase 2 to
513
- # remove the placeholder cascade.
514
- a("> **Resolution**: Review during Step 4 IaC Planning — apply an exemption, use an allowed alternative, or update the policy scope.\n")
515
- a("")
516
-
517
- # Required Tags
518
- a("## 🏷️ Required Tags\n")
519
- if tags_required:
520
- # Enrich unresolved tag entries with assignment_parameters from matching findings.
521
- # tags_required entries from cached baselines lack params; the matching findings carry them.
522
- findings_by_display_name: dict[str, dict[str, Any]] = {}
523
- for f in findings:
524
- dn = f.get("display_name", "")
525
- if dn and dn not in findings_by_display_name:
526
- findings_by_display_name[dn] = f
527
- enriched_tags: list[dict[str, Any]] = []
528
- for t in tags_required:
529
- if t.get("unresolved") or t.get("name", "").startswith("[unresolved"):
530
- source = t.get("source_assignment", "")
531
- matching = findings_by_display_name.get(source)
532
- if matching and matching.get("assignment_parameters"):
533
- t = dict(t)
534
- t["assignment_parameters"] = matching["assignment_parameters"]
535
- enriched_tags.append(t)
536
- resolved, unresolved = _split_tags(enriched_tags)
537
- a("All resources must include the following tags:\n")
538
- if unresolved:
539
- a("> **Note**: Some tag names could not be resolved from cached policy data. "
540
- "Run with `--refresh` for full tag resolution.\n")
541
- a("| Tag Name | Source Policy |")
542
- a("| --- | --- |")
543
- for t in resolved:
544
- a(f"| `{t['name']}` | {t.get('source_assignment', t.get('source_policy', ''))} |")
545
- for t in unresolved:
546
- a(f"| [unresolved] | {t.get('source_assignment', t.get('source_policy', ''))} — tag key requires live discovery |")
547
- else:
548
- a("No tag-enforcement policies discovered.\n")
549
- a("")
550
- a("```mermaid")
551
- a("%%{init: {'theme':'neutral'}}%%")
552
- a("flowchart TD")
553
- a(' MG["Management Group Tags"] -->|inherited| SUB["Subscription Tags"]')
554
- a(' SUB -->|inherited| RG["Resource Group Tags"]')
555
- a(' RG -->|inherited| RES["Resource Tags"]')
556
- a(' POL["Azure Policy\\n(Modify effect)"] -->|auto-applies| RES')
557
- a(" style POL fill:#FFB900,stroke:#333")
558
- a(" style RES fill:#0078D4,color:#fff,stroke:#333")
559
- a("```\n")
560
-
561
- # Security Policies — pre-built list already computed before Discovery Source section.
562
- a("## 🔐 Security Policies\n")
563
- if security:
564
- a("| Policy | Effect | Status |")
565
- a("| --- | --- | --- |")
566
- for f in security:
567
- icon = "❌" if f.get("classification") == "blocker" else "✅"
568
- a(f"| {f.get('display_name', '')} | {f.get('effect', '')} | {icon} |")
569
- else:
570
- a("✅ No security-specific policies discovered.\n")
571
- a("")
572
-
573
- # Cost Policies — also pick up cost-related blockers
574
- a("## 💰 Cost Policies\n")
575
- cost = list(by_category.get("Cost", []) + by_category.get("Budget", []))
576
- cost_keywords = {"Block VM SKU", "Block Azure OpenAI Provisioned", "Block Azure Sentinel Commitment",
577
- "Deny AKS deployment with agent pool count", "Deny VMSS deployment with instance count"}
578
- for f in findings:
579
- if f not in cost and any(kw in (f.get("display_name") or "") for kw in cost_keywords):
580
- cost.append(f)
581
- if cost:
582
- a("| Policy | Effect | Constraint |")
583
- a("| --- | --- | --- |")
584
- for f in cost:
585
- constraint = _extract_constraint_value(f) or "See policy parameters"
586
- a(f"| {f.get('display_name', '')} | {f.get('effect', '')} | {constraint} |")
587
- else:
588
- a("No cost-specific policies discovered.\n")
589
- a("")
590
-
591
- # Network Policies
592
- a("## 🌐 Network Policies\n")
593
- network = list(by_category.get("Network", []) + by_category.get("Networking", []))
594
- network_keywords = {"vNet peering", "virtual network", "subnet", "NSG", "firewall"}
595
- for f in findings:
596
- if f not in network and any(kw.lower() in (f.get("display_name") or "").lower() for kw in network_keywords):
597
- network.append(f)
598
- if network:
599
- a("| Policy | Effect | Constraint |")
600
- a("| --- | --- | --- |")
601
- for f in network:
602
- constraint = _extract_constraint_value(f) or "See policy parameters"
603
- a(f"| {f.get('display_name', '')} | {f.get('effect', '')} | {constraint} |")
604
- else:
605
- a("No network-specific policies discovered.\n")
606
- location_constraints = envelope.get("location_constraints", [])
607
- if location_constraints:
608
- a("### Location Governance\n")
609
- a("| Policy | Effect | Enforcement | Allowed Locations |")
610
- a("| --- | --- | --- | --- |")
611
- for constraint in location_constraints:
612
- allowed = ", ".join(f"`{value}`" for value in constraint.get("allowed_locations", [])) or "N/A"
613
- a(
614
- f"| {constraint.get('display_name', '')} | {constraint.get('effect', '')} "
615
- f"| {constraint.get('enforcement_mode', '')} | {allowed} |"
616
- )
617
- a("")
618
-
619
- # Compliance Frameworks — notable audit/compliance assignments not in findings
620
- assignment_inventory = envelope.get("assignment_inventory", [])
621
- compliance_keywords = {
622
- "GDPR", "PCI DSS", "HIPAA", "SOC", "ISO 27001", "NIST",
623
- "Multi Factor Authentication", "MFA", "Security Benchmark",
624
- "Security Baseline", "CIS",
625
- }
626
- # Collect display names already in findings to avoid duplicates
627
- finding_names = {f.get("display_name", "") for f in findings}
628
- notable_assignments = []
629
- for inv in assignment_inventory:
630
- dn = inv.get("displayName") or inv.get("display_name") or ""
631
- if dn in finding_names:
632
- continue
633
- if any(kw.lower() in dn.lower() for kw in compliance_keywords):
634
- notable_assignments.append(inv)
635
- if notable_assignments:
636
- a("## 📜 Compliance Frameworks\n")
637
- a("> These audit/compliance assignments are active at subscription or management-group scope. ")
638
- a("> While they do not block deployments (audit effect), they may impose architecture constraints ")
639
- a("> (data residency, encryption, access logging, network segmentation).\n")
640
- a("| Assignment | Scope | Type |")
641
- a("| --- | --- | --- |")
642
- for inv in notable_assignments:
643
- dn = inv.get("displayName") or inv.get("display_name") or ""
644
- scope = inv.get("scope", "")
645
- atype = inv.get("assignmentType", "")
646
- a(f"| {dn} | {scope} | {atype} |")
647
- a("")
648
- else:
649
- a("## 📜 Compliance Frameworks\n")
650
- a("✅ No compliance framework assignments (GDPR, PCI DSS, HIPAA, etc.) discovered at subscription or management-group scope.\n")
651
-
652
- # References
653
- a("## References\n")
654
- a("| Topic | Link |")
655
- a("| --- | --- |")
656
- a("| Azure Policy | [Overview](https://learn.microsoft.com/azure/governance/policy/overview) |")
657
- a("| Tag Governance | [Tagging Strategy](https://learn.microsoft.com/azure/cloud-adoption-framework/ready/azure-best-practices/resource-tagging) |\n")
658
- security_exceptions = envelope.get("security_exceptions", [])
659
- if security_exceptions:
660
- a("## Approved Security Exceptions\n")
661
- a("| ID | Control | Environment | Workload | Expires |")
662
- a("| --- | --- | --- | --- | --- |")
663
- for exception in security_exceptions:
664
- scope = exception.get("scope") or {}
665
- a(
666
- f"| `{exception.get('id', '')}` | `{exception.get('control', '')}` "
667
- f"| `{scope.get('environment', '')}` | `{scope.get('workload', '')}` "
668
- f"| `{exception.get('expires_at', '')}` |"
669
- )
670
- a("")
671
- a("---\n")
672
- footer_source = "cached governance baseline" if is_cached else "Azure Policy REST API via discover.py"
673
- a(f"_Governance constraints discovered from {footer_source}._\n")
674
-
675
- preview_path.write_text("\n".join(lines) + "\n")
676
- return preview_path