@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
package/dist/mcp.js CHANGED
@@ -1,18 +1,359 @@
1
- import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
- import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
1
+ import { Server } from "@modelcontextprotocol/server";
2
+ import { serveStdio, StdioServerTransport } from "@modelcontextprotocol/server/stdio";
3
3
  import { z } from "zod";
4
+ import { createHash, createHmac, randomBytes, timingSafeEqual } from "node:crypto";
5
+ import { lstatSync } from "node:fs";
6
+ import { realpath } from "node:fs/promises";
7
+ import { isAbsolute, resolve } from "node:path";
4
8
  import { ApexService, SUPPORTED_ARTIFACT_KINDS } from "./service.js";
5
9
  import { APEX_VERSION } from "./version.js";
10
+ import { ApexError, EXIT_CODES, normalizeError, remediationForApexError } from "./errors.js";
11
+ import { SECRET_VALUE_PATTERN } from "@apexops/contracts";
12
+ import { MCP_DOCTOR_CHECK_LIMIT, MCP_OUTPUT_SCHEMAS } from "./mcp-output-schemas.js";
13
+ import { TARGET_SCOPE_HINT, TARGET_SCOPE_PATTERN } from "./target-scope.js";
14
+ import { resolveMcpWorkspace } from "./workspace-root.js";
15
+ import { runtimeMismatchError, runtimeMismatchStatus, workspaceRuntimeBinding } from "./runtime-binding.js";
16
+ import { MCP_TOOL_EFFECTS } from "./mcp-tool-effects.js";
17
+ const errorMessages = {
18
+ APEX_USAGE: "Invalid operation arguments; check the tool input contract.",
19
+ APEX_NOT_FOUND: "Requested APEX state was not found; refresh status and check the identifier.",
20
+ APEX_CONFLICT: "The operation conflicts with current state; refresh status before retrying.",
21
+ APEX_WRITER_CONFLICT: "Another worktree owns this run's writer lease; retry from that worktree or release the lease.",
22
+ APEX_WORKSPACE_UNSUPPORTED: "The workspace path cannot be resolved to a supported APEX checkout; use a non-bare checkout or worktree.",
23
+ APEX_RUNTIME_MISMATCH: "This APEX runtime does not match the workspace runtime lock version.",
24
+ APEX_VALIDATION: "APEX validation failed; check the supplied input against the current task contract.",
25
+ APEX_STALE: "Task is stale or expired; refresh status before retrying.",
26
+ APEX_AUTHORIZATION: "Operation is not authorized in the current workflow state; check status and approval requirements.",
27
+ APEX_CURSOR_INVALID: "Cursor is invalid for this tool, workspace, or server session.",
28
+ APEX_RESULT_TOO_LARGE: "MCP result exceeded the bounded result size and cannot be paged safely.",
29
+ APEX_REVIEW_PENDING: "A rubber-duck review is waiting for its capture; operations that approve, delete or publish are blocked until it completes or is cancelled.",
30
+ APEX_INTERNAL: "APEX could not complete the operation.",
31
+ };
32
+ export const MCP_SERVER_INSTRUCTIONS = [
33
+ "APEX is a governed Azure workload lifecycle server; the kernel owns state, gates, authorization, and evidence.",
34
+ "Every tool call must include workspace as an absolute checkout or git worktree path.",
35
+ "Call status first, then use returned task, run, expected head, and owner epoch values exactly.",
36
+ "Do not retry mutations blindly after timeout, cancellation, or conflict; refresh status and confirm intent first.",
37
+ "Use ask_user for human approvals, risk decisions, missing inputs, and any choice the kernel requires.",
38
+ "Large read results may include nextCursor; call the same tool with the same workspace and cursor until it is absent.",
39
+ ].join(" ");
40
+ export const MCP_MAX_SERIALIZED_RESULT_BYTES = 64 * 1024;
41
+ const cursorInput = z.string().min(1).max(4096).optional();
42
+ const pagePaths = {
43
+ taskContext: ["inputs"],
44
+ readTaskInput: ["content"],
45
+ projectList: ["projects"],
46
+ preview: ["markdown"],
47
+ inventory: ["resources"],
48
+ improvementObservations: ["observations"],
49
+ improvementProposals: ["proposals"],
50
+ render: ["markdown"],
51
+ doctorChecks: ["checks"],
52
+ };
53
+ function serviceResolver(serviceOrResolver) {
54
+ if (typeof serviceOrResolver.resolve === "function" &&
55
+ serviceOrResolver.defaultService !== undefined) {
56
+ return serviceOrResolver;
57
+ }
58
+ const service = serviceOrResolver;
59
+ return {
60
+ defaultService: service,
61
+ resolve: async (workspace) => {
62
+ const resolved = await resolveMcpWorkspace(workspace);
63
+ const serviceRoot = await realpath(service.root);
64
+ const requestedRoot = resolve(resolved.root);
65
+ const boundRoot = resolve(serviceRoot);
66
+ const matches = process.platform === "win32"
67
+ ? requestedRoot.toLocaleLowerCase() === boundRoot.toLocaleLowerCase()
68
+ : requestedRoot === boundRoot;
69
+ if (!matches) {
70
+ throw new ApexError("APEX_WORKSPACE_UNSUPPORTED", `Workspace ${resolved.workspace} resolves to ${requestedRoot}, but this MCP server is bound to ${boundRoot}; start the server with a workspace-aware service resolver for multi-worktree use`, EXIT_CODES.validation);
71
+ }
72
+ return { service, workspace: resolved.workspace };
73
+ },
74
+ };
75
+ }
76
+ const workspaceInput = z.string().superRefine((workspace, context) => {
77
+ if (!isAbsolute(workspace)) {
78
+ context.addIssue({ code: "custom", message: "workspace must be an absolute path" });
79
+ return;
80
+ }
81
+ try {
82
+ if (!lstatSync(workspace).isDirectory()) {
83
+ context.addIssue({ code: "custom", message: "workspace must be an existing directory" });
84
+ }
85
+ }
86
+ catch {
87
+ context.addIssue({ code: "custom", message: "workspace must be an existing directory" });
88
+ }
89
+ });
6
90
  const artifactKind = z.enum(SUPPORTED_ARTIFACT_KINDS);
7
- const taskOutput = z.object({ kind: artifactKind, value: z.unknown(), summary: z.string().optional() });
8
- const reviewFinding = z
91
+ const taskOutput = z.object({ kind: artifactKind, value: z.unknown(), summary: z.string().optional() }).strict();
92
+ const stagingInput = (optional) => z
9
93
  .object({
10
- id: z.string().min(1),
11
- severity: z.enum(["critical", "high", "medium", "low", "info"]),
12
- title: z.string().min(1),
13
- detail: z.string().min(1),
94
+ taskId: z.string().min(1).max(128),
95
+ kind: artifactKind.optional(),
96
+ value: z.unknown().optional(),
97
+ summary: z.string().max(4096).optional(),
98
+ outputs: z.array(taskOutput).min(1).max(32).optional(),
14
99
  })
15
- .strict();
100
+ .strict()
101
+ .superRefine((input, context) => {
102
+ const single = input.kind !== undefined && Object.hasOwn(input, "value");
103
+ const anySingle = input.kind !== undefined || Object.hasOwn(input, "value") || input.summary !== undefined;
104
+ if ((input.outputs !== undefined && anySingle) ||
105
+ (input.outputs === undefined && (anySingle ? !single : !optional)))
106
+ context.addIssue({
107
+ code: "custom",
108
+ message: "Supply exactly one complete kind/value form or a nonempty outputs bundle.",
109
+ });
110
+ if (input.outputs && new Set(input.outputs.map(({ kind }) => kind)).size !== input.outputs.length)
111
+ context.addIssue({ code: "custom", message: "Output kinds must be unique." });
112
+ })
113
+ .meta({
114
+ oneOf: [
115
+ { required: ["outputs"], not: { anyOf: ["kind", "value", "summary"].map((key) => ({ required: [key] })) } },
116
+ { required: ["kind", "value"], not: { required: ["outputs"] } },
117
+ ...(optional
118
+ ? [{ not: { anyOf: ["kind", "value", "summary", "outputs"].map((key) => ({ required: [key] })) } }]
119
+ : []),
120
+ ],
121
+ });
122
+ export { MCP_TOOL_EFFECTS, MCP_TOOL_REVIEW_GUARDS } from "./mcp-tool-effects.js";
123
+ /** Arguments naming workspace files whose content, not only path, identifies a repeated call. */
124
+ const repeatFileArguments = {
125
+ governanceImport: ["path"],
126
+ governanceSelect: ["path"],
127
+ };
128
+ const readOnlyTools = new Set(Object.entries(MCP_TOOL_EFFECTS)
129
+ .filter(([, effect]) => effect === "read-only")
130
+ .map(([name]) => name));
131
+ /** Tools in the `read-only` effect class. Every other APEX tool is state-changing, which the rubber-duck deny hook enforces. */
132
+ export const MCP_READ_ONLY_TOOLS = readOnlyTools;
133
+ /**
134
+ * The tool effect policy the plugin build ships beside the managed hooks (apex-mcp-tools.json), so the rubber-duck deny
135
+ * hook and the MCP annotations share one source.
136
+ */
137
+ export function mcpToolPolicy() {
138
+ return {
139
+ server: "apex",
140
+ tools: Object.keys(MCP_OUTPUT_SCHEMAS).sort(),
141
+ readOnly: [...MCP_READ_ONLY_TOOLS].sort(),
142
+ };
143
+ }
144
+ const externalTools = new Set(["reconcile", "inventory", "diagnose", "doctor", "doctorChecks"]);
145
+ function assertBoundedInput(value) {
146
+ const stack = [{ value, depth: 0 }];
147
+ let nodes = 0;
148
+ let bytes = 0;
149
+ while (stack.length > 0) {
150
+ const entry = stack.pop();
151
+ if (++nodes > 100_000 || entry.depth > 64 || bytes > 4 * 1024 * 1024)
152
+ throw new ApexError("APEX_VALIDATION", "Input budget exceeded", EXIT_CODES.validation);
153
+ if (typeof entry.value === "string")
154
+ bytes += Buffer.byteLength(entry.value);
155
+ else if (entry.value !== null && typeof entry.value === "object") {
156
+ const children = Object.entries(entry.value);
157
+ if (children.length + stack.length + nodes > 100_000)
158
+ throw new ApexError("APEX_VALIDATION", "Input budget exceeded", EXIT_CODES.validation);
159
+ for (const [key, child] of children) {
160
+ bytes += Buffer.byteLength(key);
161
+ stack.push({ value: child, depth: entry.depth + 1 });
162
+ }
163
+ }
164
+ }
165
+ if (Buffer.byteLength(JSON.stringify(value)) > 4 * 1024 * 1024)
166
+ throw new ApexError("APEX_VALIDATION", "Input budget exceeded", EXIT_CODES.validation);
167
+ }
168
+ const resultEnvelopeBytes = (structuredContent) => {
169
+ const text = JSON.stringify(structuredContent);
170
+ return Buffer.byteLength(JSON.stringify({
171
+ content: [{ type: "text", text }],
172
+ structuredContent,
173
+ }), "utf8");
174
+ };
175
+ const MCP_DOCTOR_SUMMARY_BYTES = 48 * 1024;
176
+ /**
177
+ * Bounds a doctor report for MCP. Failing checks come first, then passing checks other than per-file `managed:`
178
+ * hashes; every check left out is counted in `omitted`, and doctorChecks pages the complete list. Remedies are
179
+ * deduplicated, so no distinct remedy is dropped. CLI output keeps the full report.
180
+ */
181
+ export function summarizeDoctorReport(report) {
182
+ const failed = report.checks.filter(({ ok }) => !ok);
183
+ const passed = report.checks.filter(({ ok }) => ok);
184
+ const candidates = [...failed, ...passed.filter(({ id }) => !id.startsWith("managed:"))];
185
+ const checks = [];
186
+ const summary = () => {
187
+ const listedFailed = checks.filter(({ ok }) => !ok).length;
188
+ return {
189
+ healthy: report.healthy,
190
+ nextAction: report.nextAction,
191
+ remedies: [...new Set(report.remedies)],
192
+ counts: { total: report.checks.length, passed: passed.length, failed: failed.length },
193
+ checks: checks.map(({ id, ok, value, remedy, severity }) => ({
194
+ id,
195
+ ok,
196
+ value,
197
+ ...(remedy === undefined ? {} : { remedy }),
198
+ ...(severity === undefined ? {} : { severity }),
199
+ })),
200
+ omitted: { passed: passed.length - (checks.length - listedFailed), failed: failed.length - listedFailed },
201
+ truncated: checks.length < report.checks.length,
202
+ };
203
+ };
204
+ for (const check of candidates) {
205
+ if (checks.length >= MCP_DOCTOR_CHECK_LIMIT)
206
+ break;
207
+ checks.push(check);
208
+ if (resultEnvelopeBytes(summary()) > MCP_DOCTOR_SUMMARY_BYTES) {
209
+ checks.pop();
210
+ break;
211
+ }
212
+ }
213
+ return summary();
214
+ }
215
+ const resultHash = (value) => createHash("sha256").update(JSON.stringify(value)).digest("hex");
216
+ function cursorError(message) {
217
+ return new ApexError("APEX_CURSOR_INVALID", message, EXIT_CODES.validation);
218
+ }
219
+ function tooLargeError(tool) {
220
+ return new ApexError("APEX_RESULT_TOO_LARGE", `${tool} returned more than ${MCP_MAX_SERIALIZED_RESULT_BYTES} serialized bytes and no safe page fits`, EXIT_CODES.validation);
221
+ }
222
+ function encodeCursor(secret, payload) {
223
+ const body = Buffer.from(JSON.stringify(payload), "utf8").toString("base64url");
224
+ const mac = createHmac("sha256", secret).update(body).digest("base64url");
225
+ return `${body}.${mac}`;
226
+ }
227
+ function decodeBase64urlCursorPart(value, part) {
228
+ if (value === "" || !/^[A-Za-z0-9_-]+$/u.test(value))
229
+ throw cursorError(`Malformed cursor ${part}`);
230
+ const decoded = Buffer.from(value, "base64url");
231
+ if (decoded.toString("base64url") !== value)
232
+ throw cursorError(`Non-canonical cursor ${part}`);
233
+ return decoded;
234
+ }
235
+ function decodeCursor(secret, cursor) {
236
+ const [body, mac, extra] = cursor.split(".");
237
+ if (body === undefined || mac === undefined || extra !== undefined)
238
+ throw cursorError("Malformed cursor");
239
+ const rawBody = decodeBase64urlCursorPart(body, "payload");
240
+ const expected = createHmac("sha256", secret).update(body).digest();
241
+ const actual = decodeBase64urlCursorPart(mac, "signature");
242
+ if (actual.length !== expected.length || !timingSafeEqual(actual, expected))
243
+ throw cursorError("Tampered cursor");
244
+ let decoded;
245
+ try {
246
+ decoded = JSON.parse(rawBody.toString("utf8"));
247
+ }
248
+ catch {
249
+ throw cursorError("Malformed cursor payload");
250
+ }
251
+ if (decoded === null ||
252
+ decoded.v !== 1 ||
253
+ typeof decoded.tool !== "string" ||
254
+ typeof decoded.workspace !== "string" ||
255
+ !/^[0-9a-f]{64}$/u.test(decoded.hash) ||
256
+ !Array.isArray(decoded.path) ||
257
+ decoded.path.some((entry) => typeof entry !== "string") ||
258
+ !Number.isSafeInteger(decoded.offset) ||
259
+ decoded.offset < 0) {
260
+ throw cursorError("Invalid cursor payload");
261
+ }
262
+ return decoded;
263
+ }
264
+ function getPageTarget(value, path) {
265
+ let target = value;
266
+ for (const segment of path) {
267
+ if (target === null || typeof target !== "object" || Array.isArray(target))
268
+ return undefined;
269
+ target = target[segment];
270
+ }
271
+ return target;
272
+ }
273
+ function withPageTarget(value, path, page) {
274
+ const copy = structuredClone(value);
275
+ let target = copy;
276
+ for (const segment of path.slice(0, -1))
277
+ target = target[segment];
278
+ target[path.at(-1)] = page;
279
+ return copy;
280
+ }
281
+ function applyResultPaging(secret, tool, workspace, input, value) {
282
+ const path = pagePaths[tool];
283
+ const cursor = input.cursor;
284
+ if (cursor !== undefined && typeof cursor !== "string")
285
+ throw cursorError("Cursor must be a string");
286
+ if (path === undefined) {
287
+ if (cursor !== undefined)
288
+ throw cursorError("Tool does not accept cursors");
289
+ if (resultEnvelopeBytes(value) > MCP_MAX_SERIALIZED_RESULT_BYTES)
290
+ throw tooLargeError(tool);
291
+ return value;
292
+ }
293
+ if (cursor === undefined && resultEnvelopeBytes(value) <= MCP_MAX_SERIALIZED_RESULT_BYTES)
294
+ return value;
295
+ const hash = resultHash(value);
296
+ const payload = cursor === undefined
297
+ ? { v: 1, tool, workspace, hash, path: [...path], offset: 0 }
298
+ : decodeCursor(secret, cursor);
299
+ if (payload.tool !== tool || payload.workspace !== workspace || payload.path.join("/") !== path.join("/")) {
300
+ throw cursorError("Cursor belongs to a different tool, workspace, or result path");
301
+ }
302
+ if (payload.hash !== hash) {
303
+ throw new ApexError("APEX_STALE", "Cursor result state changed before paging completed", EXIT_CODES.stale, undefined);
304
+ }
305
+ const target = getPageTarget(value, path);
306
+ if (typeof target !== "string" && !Array.isArray(target))
307
+ throw tooLargeError(tool);
308
+ const total = target.length;
309
+ if (total === 0)
310
+ throw tooLargeError(tool);
311
+ if (payload.offset >= total)
312
+ throw cursorError("Cursor offset is outside the current result");
313
+ let best;
314
+ let low = 1;
315
+ let high = total - payload.offset;
316
+ while (low <= high) {
317
+ const count = Math.floor((low + high) / 2);
318
+ const end = payload.offset + count;
319
+ const page = typeof target === "string" ? target.slice(payload.offset, end) : target.slice(payload.offset, end);
320
+ const nextCursor = end < total ? encodeCursor(secret, { ...payload, offset: end }) : undefined;
321
+ const candidate = {
322
+ ...withPageTarget(value, path, page),
323
+ ...(nextCursor === undefined ? {} : { nextCursor }),
324
+ };
325
+ if (resultEnvelopeBytes(candidate) <= MCP_MAX_SERIALIZED_RESULT_BYTES) {
326
+ best = candidate;
327
+ low = count + 1;
328
+ }
329
+ else {
330
+ high = count - 1;
331
+ }
332
+ }
333
+ if (best === undefined)
334
+ throw tooLargeError(tool);
335
+ return best;
336
+ }
337
+ // One line per failing field: keep the first message per path, then collapse array indexes so repeated mistakes such as
338
+ // "/decisionRecords/*/alternatives/*/benefits Expected string" appear once with a count.
339
+ function validationIssues(details, limit = 8) {
340
+ const firstByPath = new Map();
341
+ for (const { path, message } of details) {
342
+ if (!firstByPath.has(String(path)))
343
+ firstByPath.set(String(path), String(message));
344
+ }
345
+ const groups = new Map();
346
+ for (const [path, message] of firstByPath) {
347
+ const pattern = path.replace(/\/\d+(?=\/|$)/gu, "/*");
348
+ const group = groups.get(`${pattern}\u0000${message}`);
349
+ if (group === undefined)
350
+ groups.set(`${pattern}\u0000${message}`, { path, message, count: 1 });
351
+ else
352
+ Object.assign(group, { path: pattern, count: group.count + 1 });
353
+ }
354
+ const lines = [...groups.values()].map(({ path, message, count }) => count === 1 ? `${path} ${message}` : `${path} ${message} (${count} places)`);
355
+ return lines.length > limit ? [...lines.slice(0, limit), `${lines.length - limit} more`] : lines;
356
+ }
16
357
  const uniqueStrings = z
17
358
  .array(z.string().min(1))
18
359
  .min(1)
@@ -66,8 +407,9 @@ const projectCreateInput = z
66
407
  projectId: z.string().regex(/^[a-z0-9]+(?:-[a-z0-9]+)*$/),
67
408
  displayName: z.string().min(1).max(256),
68
409
  environment: z.string().regex(/^[a-z0-9]+(?:-[a-z0-9]+)*$/),
69
- targetScope: z.string().min(1).max(1024).optional(),
410
+ targetScope: z.string().max(1024).regex(TARGET_SCOPE_PATTERN, `Use ${TARGET_SCOPE_HINT}`),
70
411
  iacTool: z.enum(["bicep", "terraform"]),
412
+ riskOwner: z.enum(["partner", "customer"]),
71
413
  })
72
414
  .strict();
73
415
  const projectIdInput = z.object({ projectId: z.string().regex(/^[A-Za-z0-9][A-Za-z0-9_-]{0,127}$/) }).strict();
@@ -103,8 +445,9 @@ const reviewDecisionInput = z
103
445
  .array(z
104
446
  .object({
105
447
  findingId: z.string().min(1),
106
- action: z.enum(["revise", "accept-risk"]),
107
- rationale: z.string().min(1),
448
+ action: z.enum(["revise", "accept-risk", "acknowledge", "dismiss"]),
449
+ rationale: z.string().min(1).optional(),
450
+ owner: z.string().min(1).optional(),
108
451
  expiresAt: z.string().datetime().optional(),
109
452
  })
110
453
  .strict())
@@ -116,68 +459,321 @@ const normalizeOutputs = (outputs) => outputs.map(({ kind, value, summary }) =>
116
459
  value,
117
460
  ...(summary === undefined ? {} : { summary }),
118
461
  }));
119
- export function createMcpServer(service) {
120
- const server = new McpServer({ name: "apex", version: APEX_VERSION });
121
- const result = (value) => ({
122
- content: [{ type: "text", text: JSON.stringify(value) }],
123
- structuredContent: value,
462
+ /**
463
+ * Builds the APEX MCP tool table and shared call state once, and returns a cheap, side-effect-free factory for
464
+ * low-level SDK `Server` instances. Every instance from one factory shares the service resolver, single-slot queue,
465
+ * rate limit, and cursor secret, so per-connection (stdio) and per-request (HTTP) instances behave as one server.
466
+ */
467
+ export function createMcpServerFactory(serviceOrResolver, options = {}) {
468
+ const services = serviceResolver(serviceOrResolver);
469
+ let activeService = services.defaultService;
470
+ const service = new Proxy(services.defaultService, {
471
+ get(target, property, receiver) {
472
+ const actual = activeService ?? target;
473
+ const value = Reflect.get(actual, property, receiver);
474
+ return typeof value === "function" ? value.bind(actual) : value;
475
+ },
124
476
  });
125
- server.registerTool("status", { description: "Read selected APEX run status" }, async () => result(await service.status()));
126
- server.registerTool("capabilityList", { description: "Read capability pack availability" }, async () => result(await service.capabilityList()));
127
- server.registerTool("capabilityStatus", { description: "Read one capability pack status", inputSchema: { pack: z.string() } }, async ({ pack }) => result(await service.capabilityStatus(pack)));
128
- server.registerTool("nextTask", {
129
- description: "Get the next workflow result. Handle needs_input before requesting context; only status=task returns a task.taskId.",
477
+ const queueTimeoutMs = options.queueTimeoutMs ?? 30_000;
478
+ if (!Number.isSafeInteger(queueTimeoutMs) || queueTimeoutMs < 1 || queueTimeoutMs > 30_000)
479
+ throw new Error("Invalid MCP queue timeout");
480
+ // Cursors are only valid for the server process that issued them; a restart invalidates every outstanding cursor.
481
+ const cursorSecret = randomBytes(32);
482
+ const result = (value) => {
483
+ if (value === null || typeof value !== "object" || Array.isArray(value))
484
+ throw new Error("MCP success results require an object envelope");
485
+ return {
486
+ content: [{ type: "text", text: JSON.stringify(value) }],
487
+ structuredContent: value,
488
+ };
489
+ };
490
+ const tools = new Map();
491
+ const toolDefinitions = [];
492
+ let active = false;
493
+ const waiting = [];
494
+ const release = () => {
495
+ const next = waiting.shift();
496
+ if (next === undefined)
497
+ active = false;
498
+ else
499
+ next.start();
500
+ };
501
+ const acquire = (signal) => {
502
+ if (signal?.aborted)
503
+ return Promise.reject(new ApexError("APEX_CONFLICT", "Cancelled", EXIT_CODES.conflict));
504
+ if (!active) {
505
+ active = true;
506
+ return Promise.resolve(release);
507
+ }
508
+ if (waiting.length >= 31)
509
+ return Promise.reject(new ApexError("APEX_CONFLICT", "Queue full", EXIT_CODES.conflict));
510
+ return new Promise((resolve, reject) => {
511
+ const cleanup = () => {
512
+ clearTimeout(timer);
513
+ signal?.removeEventListener("abort", cancel);
514
+ };
515
+ const cancel = () => {
516
+ const index = waiting.indexOf(waiter);
517
+ if (index < 0)
518
+ return;
519
+ waiting.splice(index, 1);
520
+ cleanup();
521
+ reject(new ApexError("APEX_CONFLICT", "Queue cancelled or expired", EXIT_CODES.conflict));
522
+ };
523
+ const waiter = {
524
+ start: () => {
525
+ cleanup();
526
+ resolve(release);
527
+ },
528
+ };
529
+ const timer = setTimeout(cancel, queueTimeoutMs);
530
+ waiting.push(waiter);
531
+ signal?.addEventListener("abort", cancel, { once: true });
532
+ if (signal?.aborted)
533
+ cancel();
534
+ });
535
+ };
536
+ let rateWindowStart = Date.now();
537
+ let rateCount = 0;
538
+ function registerTool(name, config, callback) {
539
+ if (tools.has(name))
540
+ throw new Error(`Duplicate MCP tool ${name}`);
541
+ const outputSchema = MCP_OUTPUT_SCHEMAS[name];
542
+ if (outputSchema === undefined)
543
+ throw new Error(`Missing output schema for ${name}`);
544
+ const effect = MCP_TOOL_EFFECTS[name];
545
+ if (effect === undefined)
546
+ throw new Error(`Missing effect class for ${name}`);
547
+ const fileArguments = repeatFileArguments[name];
548
+ const originalInputSchema = config.inputSchema === undefined
549
+ ? z.object({}).strict()
550
+ : config.inputSchema instanceof z.ZodObject
551
+ ? config.inputSchema.strict().meta(config.inputSchema.meta() ?? {})
552
+ : z.object(config.inputSchema).strict();
553
+ const inputSchema = originalInputSchema
554
+ .extend({ workspace: workspaceInput })
555
+ .strict()
556
+ .meta(originalInputSchema.meta() ?? {});
557
+ const guarded = async (args, signal) => {
558
+ const extra = { signal };
559
+ const checkCancelled = () => {
560
+ if (signal.aborted)
561
+ throw new ApexError("APEX_CONFLICT", "Cancelled", EXIT_CODES.conflict);
562
+ };
563
+ let releaseSlot;
564
+ let serviceValidation;
565
+ try {
566
+ checkCancelled();
567
+ if (Date.now() - rateWindowStart >= 60_000) {
568
+ rateWindowStart = Date.now();
569
+ rateCount = 0;
570
+ }
571
+ if (++rateCount > 240)
572
+ throw new ApexError("APEX_CONFLICT", "Call rate exceeded", EXIT_CODES.conflict);
573
+ assertBoundedInput(args);
574
+ const input = inputSchema.safeParse(args);
575
+ if (!input.success) {
576
+ const issues = validationIssues(input.error.issues.map(({ path, message }) => ({ path: `/${path.map(String).join("/")}`, message })));
577
+ const reason = issues.length === 0 ? "Invalid tool arguments" : `Invalid tool arguments: ${issues.join("; ")}`;
578
+ if (!SECRET_VALUE_PATTERN.test(reason))
579
+ serviceValidation = reason;
580
+ throw new ApexError("APEX_VALIDATION", "Invalid tool arguments", EXIT_CODES.validation);
581
+ }
582
+ releaseSlot = await acquire(signal);
583
+ checkCancelled();
584
+ const { workspace, ...toolInput } = input.data;
585
+ const resolved = await services.resolve(workspace);
586
+ // Every tool call passes this one runtime binding check before the service is touched. An initialized
587
+ // workspace must be locked to exactly this runtime version; only read-only status reports a mismatch.
588
+ const binding = await workspaceRuntimeBinding(resolved.service.root);
589
+ if (binding.state === "mismatch" && name !== "status")
590
+ throw runtimeMismatchError(binding);
591
+ resolved.service.setWorkspacePath?.(resolved.workspace);
592
+ activeService = resolved.service;
593
+ let response;
594
+ try {
595
+ const execute = async () => binding.state === "mismatch"
596
+ ? result(runtimeMismatchStatus(binding))
597
+ : await Reflect.apply(callback, undefined, config.inputSchema === undefined ? [extra] : [toolInput, extra]);
598
+ // The adapter only describes the call; the kernel repeat guard behind the service decides whether a repeat
599
+ // is answered from the original result. A result that would fail the contract checks below is rejected
600
+ // before the guard can store it, so a failed call is never replayed.
601
+ response =
602
+ effect === "repeat-guarded"
603
+ ? result(await resolved.service.repeatSafe({
604
+ operation: name,
605
+ arguments: toolInput,
606
+ ...(fileArguments === undefined ? {} : { fileArguments }),
607
+ }, async () => {
608
+ const value = (await execute()).structuredContent;
609
+ if (!outputSchema.safeParse(value).success)
610
+ throw new Error("Invalid MCP result contract");
611
+ if (resultEnvelopeBytes(value) > MCP_MAX_SERIALIZED_RESULT_BYTES)
612
+ throw tooLargeError(name);
613
+ // Apply the final result budget before the guard can store the value, so a result the adapter
614
+ // rejects is never replayed.
615
+ assertBoundedInput(value);
616
+ return value;
617
+ }, signal))
618
+ : effect === "read-only"
619
+ ? await execute()
620
+ : effect === "read"
621
+ ? await resolved.service.withWorkspaceReadLock(execute, signal)
622
+ : await resolved.service.withWorkspaceWriteLock(execute, signal);
623
+ }
624
+ catch (error) {
625
+ const normalized = normalizeError(error);
626
+ const governance = typeof normalized.details?.reason === "string" &&
627
+ normalized.details.reason.startsWith("GOVERNANCE_");
628
+ if (normalized.code === "APEX_VALIDATION" || governance) {
629
+ const issues = validationIssues(Array.isArray(normalized.details)
630
+ ? normalized.details
631
+ : []);
632
+ const reason = issues.length === 0 ? normalized.message : `${normalized.message}: ${issues.join("; ")}`;
633
+ if (!SECRET_VALUE_PATTERN.test(reason))
634
+ serviceValidation = reason;
635
+ }
636
+ if (normalized.code === "APEX_WRITER_CONFLICT" && !SECRET_VALUE_PATTERN.test(normalized.message)) {
637
+ serviceValidation = normalized.message;
638
+ }
639
+ if (normalized.code === "APEX_WORKSPACE_UNSUPPORTED" && !SECRET_VALUE_PATTERN.test(normalized.message)) {
640
+ serviceValidation = normalized.message;
641
+ }
642
+ throw error;
643
+ }
644
+ if (response.structuredContent === undefined)
645
+ throw new Error("MCP success results require structuredContent");
646
+ response.structuredContent = applyResultPaging(cursorSecret, name, resolved.workspace, toolInput, response.structuredContent);
647
+ response.content = [{ type: "text", text: JSON.stringify(response.structuredContent) }];
648
+ assertBoundedInput(response.structuredContent);
649
+ if (!outputSchema.safeParse(response.structuredContent).success)
650
+ throw new Error("Invalid MCP result contract");
651
+ return response;
652
+ }
653
+ catch (error) {
654
+ const normalized = normalizeError(error);
655
+ const { code } = normalized;
656
+ if (serviceValidation === undefined &&
657
+ (code === "APEX_WRITER_CONFLICT" ||
658
+ code === "APEX_WORKSPACE_UNSUPPORTED" ||
659
+ code === "APEX_RUNTIME_MISMATCH") &&
660
+ !SECRET_VALUE_PATTERN.test(normalized.message)) {
661
+ serviceValidation = normalized.message;
662
+ }
663
+ // Input-schema and kernel validation reasons let agents correct typed input; guard, internal and secret-like
664
+ // messages stay generic.
665
+ const message = serviceValidation === undefined ? errorMessages[code] : serviceValidation.slice(0, 2_000);
666
+ return {
667
+ ...result({ error: { code, message, remediation: remediationForApexError(normalized) } }),
668
+ isError: true,
669
+ };
670
+ }
671
+ finally {
672
+ releaseSlot?.();
673
+ }
674
+ };
675
+ const inputJson = z.toJSONSchema(inputSchema, { target: "draft-7", io: "input" });
676
+ const annotations = {
677
+ readOnlyHint: readOnlyTools.has(name),
678
+ destructiveHint: !readOnlyTools.has(name),
679
+ idempotentHint: readOnlyTools.has(name),
680
+ openWorldHint: externalTools.has(name),
681
+ };
682
+ const definition = {
683
+ name,
684
+ ...(config.description === undefined ? {} : { description: config.description }),
685
+ inputSchema: inputJson,
686
+ outputSchema: z.toJSONSchema(outputSchema, { target: "draft-7" }),
687
+ annotations,
688
+ };
689
+ toolDefinitions.push(definition);
690
+ tools.set(name, { definition, call: guarded });
691
+ }
692
+ registerTool("status", { description: "Read selected APEX run status" }, async () => result(await service.workspaceStatus()));
693
+ registerTool("releaseWriter", { description: "Release this workspace's writer lease for the selected run." }, async () => result(await service.releaseWriter()));
694
+ registerTool("capabilityList", { description: "Read capability pack availability" }, async () => result({ packs: await service.capabilityList() }));
695
+ registerTool("capabilityStatus", { description: "Read one capability pack status", inputSchema: { pack: z.string() } }, async ({ pack }) => result(await service.capabilityStatus(pack)));
696
+ registerTool("nextTask", {
697
+ description: "Advance the workflow by issuing a request or task; this can write state and is not retry-safe. For status=needs_input, collect answers and call recordInput; for status=needs_review, present findings and call reviewDecide with the user's decisions. Only status=task returns a task.taskId for taskContext. Do not poll unresolved input or review results.",
130
698
  }, async () => result(await service.nextTask()));
131
- server.registerTool("taskContext", {
699
+ registerTool("taskContext", {
132
700
  description: "Read context only for the exact task.taskId returned by nextTask with status=task.",
133
- inputSchema: { taskId: z.string() },
701
+ inputSchema: { taskId: z.string(), cursor: cursorInput },
134
702
  }, async ({ taskId }) => result(await service.taskContext(taskId)));
135
- server.registerTool("readTaskInput", {
136
- description: "Read a bounded chunk of the accepted source artifact for an active review task.",
703
+ registerTool("readTaskInput", {
704
+ description: "Read authoritative UTF-8-bounded task input; inputHash selects an authorized dependency, review-metadata, or governance-findings:<ARM types> for the enforcing policies an Architecture design must map.",
137
705
  inputSchema: {
138
706
  taskId: z.string(),
139
707
  offset: z.number().int().nonnegative().optional(),
140
708
  limit: z.number().int().min(1).max(6_000).optional(),
709
+ cursor: cursorInput,
710
+ inputHash: z
711
+ .union([
712
+ z.string().regex(/^[0-9a-f]{64}$/u),
713
+ z.literal("review-metadata"),
714
+ z.string().regex(/^governance-findings:[A-Za-z0-9./,]{0,2000}$/u),
715
+ ])
716
+ .optional(),
141
717
  },
142
- }, async ({ taskId, offset, limit }) => result(await service.readTaskInput(taskId, offset, limit)));
143
- server.registerTool("recordInput", { description: "Record answers for the exact pending kernel input request", inputSchema: inputSubmission }, async (input) => result(await service.recordInput(input)));
144
- server.registerTool("projectCreate", {
145
- description: "Create and select a new project with its initial environment run",
718
+ }, async ({ taskId, offset, limit, inputHash }) => result(await service.readTaskInput(taskId, offset, limit, inputHash)));
719
+ registerTool("recordInput", {
720
+ description: "Record answers for the exact pending kernel input request",
721
+ inputSchema: inputSubmission,
722
+ }, async (input) => result(await service.recordInput(input)));
723
+ registerTool("governanceImport", {
724
+ description: "Import governance for the active discovery task: either a reviewed local subscription baseline by path (never its contents) or reference: true for the shipped ALZ Corp reference baseline.",
725
+ inputSchema: { path: z.string().min(1).optional(), reference: z.literal(true).optional() },
726
+ }, async ({ path, reference }) => {
727
+ if ((path === undefined) === (reference === undefined))
728
+ throw new ApexError("APEX_USAGE", "Provide exactly one of path or reference", EXIT_CODES.usage);
729
+ return result(await (path === undefined ? service.importGovernanceReference() : service.importGovernanceBaseline(path)));
730
+ });
731
+ registerTool("governanceSelect", {
732
+ description: "Prepare or recall the target governance snapshot reuse/refresh question; only a local path is accepted. Does not import or collect Azure policy.",
733
+ inputSchema: { path: z.string().min(1), reopen: z.boolean().optional() },
734
+ }, async ({ path, reopen }) => result(await service.selectGovernanceBaseline(path, ...(reopen === undefined ? [] : [{ reopen }]))));
735
+ registerTool("projectCreate", {
736
+ description: "Create and select a new project with its initial environment run. targetScope is the user's explicit choice: local, or a full /subscriptions/<id>/resourceGroups/<name> path.",
146
737
  inputSchema: projectCreateInput,
147
738
  }, async (input) => result(await service.createProject(input)));
148
- server.registerTool("projectList", { description: "List projects in the current workspace" }, async () => result({ projects: await service.listProjects() }));
149
- server.registerTool("projectUse", { description: "Select an existing project and optionally one of its runs", inputSchema: projectUseInput }, async ({ projectId, runId }) => result(await service.use(projectId, runId)));
150
- server.registerTool("projectDelete", {
739
+ registerTool("projectList", { description: "List projects in the current workspace", inputSchema: { cursor: cursorInput } }, async () => result({ projects: await service.listProjects() }));
740
+ registerTool("projectUse", { description: "Select an existing project and optionally one of its runs", inputSchema: projectUseInput }, async ({ projectId, runId }) => result(await service.use(projectId, runId)));
741
+ registerTool("projectDelete", {
151
742
  description: "Delete a project and all of its run-bound state after explicit confirmation",
152
743
  inputSchema: projectDeleteInput,
153
744
  }, async ({ projectId, confirm }) => result(await service.deleteProject(projectId, confirm)));
154
- server.registerTool("gateDecide", {
745
+ registerTool("gateDecide", {
155
746
  description: "Record an explicitly confirmed human decision for Gate 1, 2, or 3 using the local OS username as actor. Gate 4 remains CLI-only.",
156
747
  inputSchema: gateDecisionInput,
157
748
  }, async ({ gate, decision }) => result(await service.decideInteractiveGate(gate, decision)));
158
- server.registerTool("reviewDecide", {
159
- description: "Resolve all current review findings atomically by requesting revision or accepting permitted time-bound risk.",
749
+ registerTool("reviewDecide", {
750
+ description: "Resolve review findings atomically by revision, Requirements obligation acknowledgment with an owner, or permitted time-bound risk.",
160
751
  inputSchema: reviewDecisionInput,
161
- }, async ({ reviewHash, decisions }) => result(await service.decideReview(reviewHash, decisions.map(({ expiresAt, ...decision }) => ({
752
+ }, async ({ reviewHash, decisions }) => result(await service.decideReview(reviewHash, decisions.map(({ rationale, owner, expiresAt, ...decision }) => ({
162
753
  ...decision,
754
+ ...(rationale === undefined ? {} : { rationale }),
755
+ ...(owner === undefined ? {} : { owner }),
163
756
  ...(expiresAt === undefined ? {} : { expiresAt }),
164
757
  })))));
165
- server.registerTool("stageArtifact", {
166
- inputSchema: {
167
- taskId: z.string(),
168
- kind: artifactKind.optional(),
169
- value: z.unknown().optional(),
170
- summary: z.string().optional(),
171
- outputs: z.array(taskOutput).optional(),
172
- },
173
- }, async ({ taskId, kind, value, summary, outputs }) => {
174
- if (outputs !== undefined)
175
- return result(await Promise.all(normalizeOutputs(outputs).map((output) => service.stageArtifact(taskId, output))));
758
+ registerTool("stageArtifact", {
759
+ description: "Stage one typed artifact or an outputs[] bundle for the exact active task; staging does not complete the task.",
760
+ inputSchema: stagingInput(false),
761
+ }, async ({ taskId, kind, value, summary, outputs }, extra) => {
762
+ if (outputs !== undefined) {
763
+ const artifacts = [];
764
+ for (const output of normalizeOutputs(outputs)) {
765
+ if (extra.signal.aborted)
766
+ throw new ApexError("APEX_CONFLICT", "Cancelled", EXIT_CODES.conflict);
767
+ artifacts.push(await service.stageArtifact(taskId, output));
768
+ }
769
+ return result({ artifacts });
770
+ }
176
771
  if (kind === undefined)
177
772
  throw new Error("stageArtifact requires kind/value or outputs[]");
178
773
  return result(await service.stageArtifact(taskId, { kind, value, ...(summary === undefined ? {} : { summary }) }));
179
774
  });
180
- server.registerTool("stageFile", {
775
+ registerTool("stageFile", {
776
+ description: "Stage a generated file for the exact active task, optionally checking its expected SHA; does not deploy it.",
181
777
  inputSchema: {
182
778
  taskId: z.string(),
183
779
  path: z.string(),
@@ -188,7 +784,8 @@ export function createMcpServer(service) {
188
784
  .optional(),
189
785
  },
190
786
  }, async ({ taskId, path, content, expectedSha }) => result(await service.stageFile(taskId, path, content, expectedSha)));
191
- server.registerTool("generateIac", {
787
+ registerTool("generateIac", {
788
+ description: "Generate IaC and complete the active CodeGen task from accepted inputs and bindings. Success already accepts the manifest and handoff; return the receipt without calling completeTask again. Does not authorize deployment.",
192
789
  inputSchema: {
193
790
  taskId: z.string(),
194
791
  existingResources: z.array(z.string()).optional(),
@@ -202,52 +799,63 @@ export function createMcpServer(service) {
202
799
  ...(azapiProviderConstraint === undefined ? {} : { azapiProviderConstraint }),
203
800
  ...(lockFileContent === undefined ? {} : { lockFileContent }),
204
801
  })));
205
- server.registerTool("validateTask", {
206
- inputSchema: {
207
- taskId: z.string(),
208
- kind: artifactKind.optional(),
209
- value: z.unknown().optional(),
210
- summary: z.string().optional(),
211
- outputs: z.array(taskOutput).optional(),
212
- },
213
- }, async ({ taskId, kind, value, summary, outputs }) => result(await service.validateTask(taskId, outputs === undefined
214
- ? kind === undefined
215
- ? undefined
216
- : { kind, value, ...(summary === undefined ? {} : { summary }) }
217
- : normalizeOutputs(outputs))));
218
- server.registerTool("completeTask", {
802
+ registerTool("validateTask", {
803
+ description: "With only taskId for an IaC validation task, execute native checks and return runtime-owned outputs and execution metadata. valid:false and blockedValidatorIds mean required checks remain unexecuted; do not complete. Supplied artifacts are only checked/staged. Task completion and approval are separate.",
804
+ inputSchema: stagingInput(true),
805
+ }, async ({ taskId, kind, value, summary, outputs }, extra) => {
806
+ if (outputs !== undefined) {
807
+ const staged = [];
808
+ for (const output of normalizeOutputs(outputs)) {
809
+ if (extra.signal.aborted)
810
+ throw new ApexError("APEX_CONFLICT", "Cancelled", EXIT_CODES.conflict);
811
+ const validated = await service.validateTask(taskId, output);
812
+ if (validated.staged !== undefined)
813
+ staged.push(...(Array.isArray(validated.staged) ? validated.staged : [validated.staged]));
814
+ }
815
+ return result({ valid: true, taskId, staged });
816
+ }
817
+ return result(await service.validateTask(taskId, kind === undefined ? undefined : { kind, value, ...(summary === undefined ? {} : { summary }) }));
818
+ });
819
+ registerTool("completeTask", {
219
820
  description: "Complete a task atomically with a nonempty outputs[] bundle.",
220
821
  inputSchema: {
221
822
  taskId: z.string(),
222
823
  outputs: z.array(taskOutput).min(1),
223
824
  },
224
825
  }, async ({ taskId, outputs }) => result(await service.completeTaskOutputs(taskId, normalizeOutputs(outputs))));
225
- server.registerTool("requirementsComplete", {
826
+ registerTool("requirementsComplete", {
226
827
  description: "Complete the active Requirements task atomically.",
227
828
  inputSchema: { taskId: z.string(), requirements: z.unknown() },
228
829
  }, async ({ taskId, requirements }) => result(await service.completeRequirements(taskId, requirements)));
229
- server.registerTool("architectureComplete", {
230
- description: "Complete the active Architecture task atomically with all required outputs.",
830
+ registerTool("architectureComplete", {
831
+ description: "Complete Architecture atomically; APEX derives identity, artifact hashes, top-level requirementTraceability, and cost/SKU bindings. Each SKU and SLO decision lists its component requirementIds. policyMappings maps each governanceFindings entry from task context to a component; APEX marks findings whose resource types match no component resourceTypes not-applicable. A rejection lists every problem across all four inputs.",
231
832
  inputSchema: {
232
833
  taskId: z.string(),
233
834
  architecture: z.unknown(),
234
835
  costEstimate: z.unknown(),
235
836
  decisionManifest: z.unknown(),
837
+ policyMappings: z.array(z.unknown()),
236
838
  },
237
- }, async ({ taskId, architecture, costEstimate, decisionManifest }) => result(await service.completeArchitecture(taskId, architecture, costEstimate, decisionManifest)));
238
- server.registerTool("reviewComplete", {
239
- description: "Complete the active review task; APEX derives subject identity, hash, timestamp, and evidence binding.",
240
- inputSchema: { taskId: z.string(), findings: z.array(reviewFinding) },
241
- }, async ({ taskId, findings }) => result(await service.completeReview(taskId, findings)));
242
- server.registerTool("planComplete", {
839
+ }, async ({ taskId, architecture, costEstimate, decisionManifest, policyMappings }) => result(await service.completeArchitecture(taskId, architecture, costEstimate, decisionManifest, policyMappings)));
840
+ registerTool("reviewComplete", {
841
+ description: "Complete the active review task from rubber-duck's captured output after running rubber-duck in sync mode with the exact reviewRequest.prompt from taskContext. Takes no findings: APEX derives them only from the verified capture. A missing, edited, replayed or mismatched capture fails closed and the review counts as not done.",
842
+ inputSchema: { taskId: z.string() },
843
+ }, async ({ taskId }) => result(await service.completeReview(taskId)));
844
+ registerTool("planComplete", {
243
845
  description: "Atomically complete a plan. Derives the canonical implementation intent hash for the binding; do not supply intentHash.",
244
846
  inputSchema: planCompletionInput,
245
847
  }, async ({ taskId, implementationIntent, iacBinding, environmentInputs }) => result(await service.completePlan(taskId, implementationIntent, iacBinding, environmentInputs)));
246
- server.registerTool("preview", { description: "Read the current operator-created deployment preview" }, async () => result(await service.currentPreview()));
247
- server.registerTool("reconcile", {}, async () => result(await service.reconcile()));
248
- server.registerTool("inventory", {}, async () => result(await service.inventory()));
249
- server.registerTool("diagnose", {}, async () => result(await service.diagnose()));
250
- server.registerTool("improvementObserve", {
848
+ registerTool("preview", { description: "Read the current operator-created deployment preview", inputSchema: { cursor: cursorInput } }, async () => result({ markdown: await service.currentPreview() }));
849
+ registerTool("reconcile", { description: "Run the kernel-authorized reconciliation operation for the selected run." }, async () => result(await service.reconcile()));
850
+ registerTool("inventory", {
851
+ description: "Run the bounded inventory operation for the selected run and return its evidence.",
852
+ inputSchema: { cursor: cursorInput },
853
+ }, async () => result(await service.inventory()));
854
+ registerTool("diagnose", { description: "Run bounded diagnosis for the selected run and return the kernel-recorded result." }, async () => {
855
+ const { status, doctor } = (await service.diagnose());
856
+ return result({ status, doctor: summarizeDoctorReport(doctor) });
857
+ });
858
+ registerTool("improvementObserve", {
251
859
  description: "Submit one bounded redacted observation for the selected run",
252
860
  inputSchema: {
253
861
  taskId: z.string().optional(),
@@ -281,12 +889,43 @@ export function createMcpServer(service) {
281
889
  ...(taskId === undefined ? {} : { taskId }),
282
890
  ...(observedAt === undefined ? {} : { observedAt }),
283
891
  })));
284
- server.registerTool("improvementObservations", { description: "Read bounded observations" }, async () => result(await service.improvementObservations()));
285
- server.registerTool("improvementProposals", { description: "Read inert improvement proposals" }, async () => result(await service.improvementProposals()));
286
- server.registerTool("render", { inputSchema: { kind: z.enum(["status", "requirements", "preview", "approval", "inventory"]) } }, async ({ kind }) => result(await service.render(kind)));
287
- server.registerTool("promote", { inputSchema: { environment: z.string(), target: z.string() } }, async ({ environment, target }) => result(await service.promote(environment, target)));
288
- server.registerTool("doctor", { inputSchema: { fix: z.boolean().optional(), yes: z.boolean().optional() } }, async ({ fix, yes }) => result(await service.doctor(fix, yes)));
289
- server.registerTool("submitEvidence", {
892
+ registerTool("improvementObservations", { description: "Read bounded observations", inputSchema: { cursor: cursorInput } }, async () => result({ observations: await service.improvementObservations() }));
893
+ registerTool("improvementProposals", { description: "Read inert improvement proposals", inputSchema: { cursor: cursorInput } }, async () => result({ proposals: await service.improvementProposals() }));
894
+ registerTool("render", {
895
+ description: "Render the selected run's status, requirements, preview, approval, inventory, structured Architecture decisions, implementation plan, plan-bound deployment guide, operational runbook, or evidence-bound deployment summary as a human-readable projection.",
896
+ inputSchema: {
897
+ kind: z.enum([
898
+ "status",
899
+ "requirements",
900
+ "preview",
901
+ "approval",
902
+ "inventory",
903
+ "deployment-summary",
904
+ "deployment-guide",
905
+ "implementation-plan",
906
+ "architecture-decisions",
907
+ "operations-runbook",
908
+ ]),
909
+ cursor: cursorInput,
910
+ },
911
+ }, async ({ kind }) => result({ markdown: await service.render(kind) }));
912
+ registerTool("promote", {
913
+ description: "Promote the selected run to a target environment through kernel checks; does not approve or execute deployment.",
914
+ inputSchema: { environment: z.string(), target: z.string() },
915
+ }, async ({ environment, target }) => result(await service.promote(environment, target)));
916
+ registerTool("doctor", {
917
+ description: "Inspect local APEX installation health; request repairs with fix and explicit confirmation with yes. Returns counts, remedies, and a bounded check list with failing checks first; when truncated, read every check with doctorChecks.",
918
+ inputSchema: { fix: z.boolean().optional(), yes: z.boolean().optional() },
919
+ }, async ({ fix, yes }) => result(summarizeDoctorReport(await service.doctor(fix, yes))));
920
+ registerTool("doctorChecks", {
921
+ description: "Read every local APEX installation health check without repairing; failedOnly limits the list to failing checks.",
922
+ inputSchema: { failedOnly: z.boolean().optional(), cursor: cursorInput },
923
+ }, async ({ failedOnly }) => {
924
+ const { checks } = await service.doctor();
925
+ return result({ checks: failedOnly === true ? checks.filter(({ ok }) => !ok) : checks });
926
+ });
927
+ registerTool("submitEvidence", {
928
+ description: "Submit JSON evidence bound to the exact active task after validating its context; does not complete the task.",
290
929
  inputSchema: {
291
930
  taskId: z.string(),
292
931
  kind: z.string(),
@@ -297,9 +936,83 @@ export function createMcpServer(service) {
297
936
  await service.taskContext(taskId);
298
937
  return result(await service.acceptEvidence({ kind, contentType: "application/json", value, required: required ?? false }));
299
938
  });
300
- return server;
939
+ // Unknown tool names keep the v1-era externally visible shape (an isError tool result, not a JSON-RPC error), now
940
+ // as the standard APEX error envelope so clients parse one error contract.
941
+ const unknownTool = (name) => {
942
+ const label = typeof name === "string" && /^[A-Za-z][A-Za-z0-9_-]{0,63}$/u.test(name) ? ` ${name}` : "";
943
+ const error = new ApexError("APEX_USAGE", `Unknown tool${label}; call tools/list for available tools`, EXIT_CODES.usage);
944
+ return {
945
+ ...result({ error: { code: error.code, message: error.message, remediation: remediationForApexError(error) } }),
946
+ isError: true,
947
+ };
948
+ };
949
+ return () => {
950
+ const server = new Server({ name: "apex", version: APEX_VERSION }, { capabilities: { tools: {} }, instructions: MCP_SERVER_INSTRUCTIONS });
951
+ server.setRequestHandler("tools/list", () => ({ tools: toolDefinitions }));
952
+ server.setRequestHandler("tools/call", async (request, ctx) => {
953
+ const tool = tools.get(request.params.name);
954
+ if (tool === undefined)
955
+ return unknownTool(request.params.name);
956
+ const response = await tool.call(request.params.arguments ?? {}, ctx.mcpReq.signal);
957
+ return server.projectCallToolResult(response, tool.definition.outputSchema);
958
+ });
959
+ return server;
960
+ };
301
961
  }
302
- export async function serveMcp(service) {
303
- await createMcpServer(service).connect(new StdioServerTransport());
962
+ export function createMcpServer(serviceOrResolver, options = {}) {
963
+ return createMcpServerFactory(serviceOrResolver, options)();
964
+ }
965
+ /**
966
+ * Serves APEX over stdio until the connection ends (stdin EOF), the transport fails, or SIGINT/SIGTERM arrives.
967
+ * `serveStdio` answers `server/discover` for protocol 2026-07-28 and, with `legacy: "serve"`, still serves a 2025-era
968
+ * `initialize` (including the discover-then-initialize fallback) from the same factory. Stdout stays protocol-only.
969
+ * A stdin error closes the connection and rejects. `streams` defaults to the process stdio.
970
+ */
971
+ export async function serveMcp(serviceOrResolver, streams = {}) {
972
+ const factory = createMcpServerFactory(serviceOrResolver);
973
+ const stdin = streams.stdin ?? process.stdin;
974
+ const stdout = streams.stdout ?? process.stdout;
975
+ await new Promise((resolve, reject) => {
976
+ let settled = false;
977
+ let failure;
978
+ let handle;
979
+ const signals = ["SIGINT", "SIGTERM"];
980
+ const cleanup = () => {
981
+ stdin.off("error", fail);
982
+ for (const signal of signals)
983
+ process.off(signal, shutdown);
984
+ };
985
+ // Every exit path funnels through the transport closing; a recorded stream failure keeps the promise rejecting.
986
+ const finish = () => {
987
+ if (settled)
988
+ return;
989
+ settled = true;
990
+ cleanup();
991
+ if (failure === undefined)
992
+ resolve();
993
+ else
994
+ reject(failure);
995
+ };
996
+ const shutdown = () => {
997
+ void (handle?.close() ?? Promise.resolve()).then(finish, (error) => {
998
+ failure ??= error instanceof Error ? error : new Error(String(error));
999
+ finish();
1000
+ });
1001
+ };
1002
+ function fail(error) {
1003
+ failure ??= error;
1004
+ shutdown();
1005
+ }
1006
+ class ApexStdioTransport extends StdioServerTransport {
1007
+ async close() {
1008
+ await super.close();
1009
+ finish();
1010
+ }
1011
+ }
1012
+ stdin.once("error", fail);
1013
+ for (const signal of signals)
1014
+ process.once(signal, shutdown);
1015
+ handle = serveStdio(factory, { legacy: "serve", transport: new ApexStdioTransport(stdin, stdout) });
1016
+ });
304
1017
  }
305
1018
  //# sourceMappingURL=mcp.js.map