@raishin/vanguard-frontier-agentic 3.11.0 → 3.12.0

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 (393) hide show
  1. package/.agents/tasks/task-rust-tui-implementation/2025-01-15-120000-review.md +1 -1
  2. package/.agents/tasks/task-rust-tui-implementation/task.json +1 -1
  3. package/.claude-plugin/marketplace.json +2 -2
  4. package/.claude-plugin/plugin.json +7 -1
  5. package/.cursor-plugin/plugin.json +25 -1
  6. package/.github/plugin/marketplace.json +1 -1
  7. package/README.md +13 -13
  8. package/agents/AGENTS.md +24 -24
  9. package/agents/README.md +17 -17
  10. package/agents/ionos/ionos-cost-optimization-analyst-agent/metadata.json +17 -3
  11. package/agents/ionos/ionos-datacenter-designer-reviewer-agent/metadata.json +17 -3
  12. package/agents/ionos/ionos-kubernetes-platform-operator-agent/metadata.json +17 -3
  13. package/agents/ionos/ionos-live-database-lifecycle-guard-agent/metadata.json +17 -3
  14. package/agents/ionos/ionos-maestro-agent/metadata.json +17 -3
  15. package/agents/ionos/ionos-security-compliance-reviewer-agent/metadata.json +17 -3
  16. package/agents/istio/README.md +16 -8
  17. package/agents/istio/istio-ambient-mesh-review-agent/AGENT.md +19 -23
  18. package/agents/istio/istio-ambient-mesh-review-agent/harnesses/claude-code.agent.md +20 -20
  19. package/agents/istio/istio-ambient-mesh-review-agent/harnesses/codex.toml +34 -17
  20. package/agents/istio/istio-ambient-mesh-review-agent/harnesses/copilot.agent.md +26 -20
  21. package/agents/istio/istio-ambient-mesh-review-agent/harnesses/cursor.agent.md +20 -20
  22. package/agents/istio/istio-ambient-mesh-review-agent/harnesses/gemini.agent.md +20 -20
  23. package/agents/istio/istio-ambient-mesh-review-agent/harnesses/kiro-cli.agent.json +2 -2
  24. package/agents/istio/istio-ambient-mesh-review-agent/harnesses/kiro-ide.agent.md +20 -20
  25. package/agents/istio/istio-ambient-mesh-review-agent/metadata.json +29 -9
  26. package/agents/istio/istio-authorization-policy-review-agent/AGENT.md +51 -0
  27. package/agents/istio/istio-authorization-policy-review-agent/harnesses/claude-code.agent.md +38 -0
  28. package/agents/istio/istio-authorization-policy-review-agent/harnesses/codex.toml +49 -0
  29. package/agents/istio/istio-authorization-policy-review-agent/harnesses/copilot.agent.md +44 -0
  30. package/agents/istio/istio-authorization-policy-review-agent/harnesses/cursor.agent.md +38 -0
  31. package/agents/istio/istio-authorization-policy-review-agent/harnesses/gemini.agent.md +38 -0
  32. package/agents/istio/istio-authorization-policy-review-agent/harnesses/kiro-cli.agent.json +5 -0
  33. package/agents/istio/istio-authorization-policy-review-agent/harnesses/kiro-ide.agent.md +38 -0
  34. package/agents/istio/istio-authorization-policy-review-agent/metadata.json +50 -0
  35. package/agents/istio/istio-dataplane-diagnostics-agent/AGENT.md +51 -0
  36. package/agents/istio/istio-dataplane-diagnostics-agent/harnesses/claude-code.agent.md +38 -0
  37. package/agents/istio/istio-dataplane-diagnostics-agent/harnesses/codex.toml +49 -0
  38. package/agents/istio/istio-dataplane-diagnostics-agent/harnesses/copilot.agent.md +44 -0
  39. package/agents/istio/istio-dataplane-diagnostics-agent/harnesses/cursor.agent.md +38 -0
  40. package/agents/istio/istio-dataplane-diagnostics-agent/harnesses/gemini.agent.md +38 -0
  41. package/agents/istio/istio-dataplane-diagnostics-agent/harnesses/kiro-cli.agent.json +5 -0
  42. package/agents/istio/istio-dataplane-diagnostics-agent/harnesses/kiro-ide.agent.md +38 -0
  43. package/agents/istio/istio-dataplane-diagnostics-agent/metadata.json +50 -0
  44. package/agents/istio/istio-gateway-api-review-agent/AGENT.md +51 -0
  45. package/agents/istio/istio-gateway-api-review-agent/harnesses/claude-code.agent.md +38 -0
  46. package/agents/istio/istio-gateway-api-review-agent/harnesses/codex.toml +49 -0
  47. package/agents/istio/istio-gateway-api-review-agent/harnesses/copilot.agent.md +44 -0
  48. package/agents/istio/istio-gateway-api-review-agent/harnesses/cursor.agent.md +38 -0
  49. package/agents/istio/istio-gateway-api-review-agent/harnesses/gemini.agent.md +38 -0
  50. package/agents/istio/istio-gateway-api-review-agent/harnesses/kiro-cli.agent.json +5 -0
  51. package/agents/istio/istio-gateway-api-review-agent/harnesses/kiro-ide.agent.md +38 -0
  52. package/agents/istio/istio-gateway-api-review-agent/metadata.json +50 -0
  53. package/agents/istio/istio-maestro-agent/AGENT.md +51 -0
  54. package/agents/istio/istio-maestro-agent/harnesses/claude-code.agent.md +38 -0
  55. package/agents/istio/istio-maestro-agent/harnesses/codex.toml +49 -0
  56. package/agents/istio/istio-maestro-agent/harnesses/copilot.agent.md +44 -0
  57. package/agents/istio/istio-maestro-agent/harnesses/cursor.agent.md +38 -0
  58. package/agents/istio/istio-maestro-agent/harnesses/gemini.agent.md +38 -0
  59. package/agents/istio/istio-maestro-agent/harnesses/kiro-cli.agent.json +5 -0
  60. package/agents/istio/istio-maestro-agent/harnesses/kiro-ide.agent.md +38 -0
  61. package/agents/istio/istio-maestro-agent/metadata.json +44 -0
  62. package/agents/istio/istio-traffic-resilience-review-agent/AGENT.md +51 -0
  63. package/agents/istio/istio-traffic-resilience-review-agent/harnesses/claude-code.agent.md +38 -0
  64. package/agents/istio/istio-traffic-resilience-review-agent/harnesses/codex.toml +49 -0
  65. package/agents/istio/istio-traffic-resilience-review-agent/harnesses/copilot.agent.md +44 -0
  66. package/agents/istio/istio-traffic-resilience-review-agent/harnesses/cursor.agent.md +38 -0
  67. package/agents/istio/istio-traffic-resilience-review-agent/harnesses/gemini.agent.md +38 -0
  68. package/agents/istio/istio-traffic-resilience-review-agent/harnesses/kiro-cli.agent.json +5 -0
  69. package/agents/istio/istio-traffic-resilience-review-agent/harnesses/kiro-ide.agent.md +38 -0
  70. package/agents/istio/istio-traffic-resilience-review-agent/metadata.json +50 -0
  71. package/agents/istio/istio-upgrade-readiness-agent/AGENT.md +51 -0
  72. package/agents/istio/istio-upgrade-readiness-agent/harnesses/claude-code.agent.md +38 -0
  73. package/agents/istio/istio-upgrade-readiness-agent/harnesses/codex.toml +49 -0
  74. package/agents/istio/istio-upgrade-readiness-agent/harnesses/copilot.agent.md +44 -0
  75. package/agents/istio/istio-upgrade-readiness-agent/harnesses/cursor.agent.md +38 -0
  76. package/agents/istio/istio-upgrade-readiness-agent/harnesses/gemini.agent.md +38 -0
  77. package/agents/istio/istio-upgrade-readiness-agent/harnesses/kiro-cli.agent.json +5 -0
  78. package/agents/istio/istio-upgrade-readiness-agent/harnesses/kiro-ide.agent.md +38 -0
  79. package/agents/istio/istio-upgrade-readiness-agent/metadata.json +50 -0
  80. package/agents/kubernetes/kubernetes-live-mesh-policy-guard-agent/AGENT.md +23 -34
  81. package/agents/kubernetes/kubernetes-live-mesh-policy-guard-agent/harnesses/claude-code.agent.md +23 -30
  82. package/agents/kubernetes/kubernetes-live-mesh-policy-guard-agent/harnesses/codex.toml +46 -21
  83. package/agents/kubernetes/kubernetes-live-mesh-policy-guard-agent/harnesses/copilot.agent.md +33 -30
  84. package/agents/kubernetes/kubernetes-live-mesh-policy-guard-agent/harnesses/cursor.agent.md +23 -30
  85. package/agents/kubernetes/kubernetes-live-mesh-policy-guard-agent/harnesses/gemini.agent.md +23 -30
  86. package/agents/kubernetes/kubernetes-live-mesh-policy-guard-agent/harnesses/kiro-cli.agent.json +2 -2
  87. package/agents/kubernetes/kubernetes-live-mesh-policy-guard-agent/harnesses/kiro-ide.agent.md +23 -30
  88. package/agents/kubernetes/kubernetes-live-mesh-policy-guard-agent/metadata.json +9 -8
  89. package/agents/kubernetes/kubernetes-live-mesh-policy-guard-agent/references/rbac-pre-flight.md +9 -2
  90. package/agents/ovhcloud/ovhcloud-cost-finops-analyst-agent/metadata.json +17 -3
  91. package/agents/ovhcloud/ovhcloud-iam-policy-review-agent/metadata.json +17 -3
  92. package/agents/ovhcloud/ovhcloud-kubernetes-platform-operator-agent/metadata.json +17 -3
  93. package/agents/ovhcloud/ovhcloud-live-kms-key-destruction-guard-agent/metadata.json +17 -3
  94. package/agents/ovhcloud/ovhcloud-maestro-agent/metadata.json +17 -3
  95. package/agents/ovhcloud/ovhcloud-network-architect-agent/metadata.json +17 -3
  96. package/agents/scaleway/scaleway-cost-optimizer-agent/metadata.json +17 -3
  97. package/agents/scaleway/scaleway-iam-policy-review-agent/metadata.json +17 -3
  98. package/agents/scaleway/scaleway-kapsule-platform-operator-agent/metadata.json +17 -3
  99. package/agents/scaleway/scaleway-live-kapsule-rollout-guard-agent/metadata.json +17 -3
  100. package/agents/scaleway/scaleway-maestro-agent/metadata.json +17 -3
  101. package/agents/scaleway/scaleway-network-architect-agent/metadata.json +17 -3
  102. package/catalog/agents.json +378 -113
  103. package/catalog/asset-integrity.json +1268 -138
  104. package/catalog/install-roles.json +14 -1
  105. package/catalog/model-assignments.json +198 -0
  106. package/catalog/model-registry.json +70 -34
  107. package/catalog/skill-manifest.json +517 -13
  108. package/catalog/skills.json +213 -8
  109. package/catalog/workflows.json +49 -0
  110. package/package.json +7 -4
  111. package/plugins/cross-platform-agent-template/LICENSE +201 -0
  112. package/plugins/cross-platform-agent-template/README.md +30 -0
  113. package/plugins/cross-platform-agent-template/SECURITY.md +18 -0
  114. package/plugins/vanguard-frontier-agentic/.codex-plugin/plugin.json +1 -1
  115. package/powers/README.md +5 -2
  116. package/powers/vanguard-istio/POWER.md +6 -5
  117. package/schemas/istio-review-contract.schema.json +284 -0
  118. package/schemas/model-policy.schema.json +1 -1
  119. package/scripts/generate-board-counts.mjs +40 -4
  120. package/scripts/generate-readme-counts.mjs +51 -2
  121. package/scripts/generate-workflow-catalog.mjs +7 -7
  122. package/scripts/istio_evidence_facts.py +359 -0
  123. package/scripts/model-policy.mjs +74 -11
  124. package/skills/istio/README.md +15 -4
  125. package/skills/istio/istio-ambient-mesh-review/SKILL.md +38 -39
  126. package/skills/istio/istio-ambient-mesh-review/agents/openai.yaml +5 -0
  127. package/skills/istio/istio-ambient-mesh-review/metadata.json +8 -8
  128. package/skills/istio/istio-ambient-mesh-review/references/applicability.md +9 -0
  129. package/skills/istio/istio-ambient-mesh-review/references/enforcement-rules.md +21 -0
  130. package/skills/istio/istio-ambient-mesh-review/references/enrollment-and-paths.md +27 -0
  131. package/skills/istio/istio-ambient-mesh-review/references/evidence-boundary.md +33 -0
  132. package/skills/istio/istio-ambient-mesh-review/references/migration-boundaries.md +19 -0
  133. package/skills/istio/istio-ambient-mesh-review/references/negative-tests.md +15 -0
  134. package/skills/istio/istio-ambient-mesh-review/references/official-sources.md +33 -32
  135. package/skills/istio/istio-ambient-mesh-review/references/output-contract.md +21 -0
  136. package/skills/istio/istio-ambient-mesh-review/references/review-contract.json +284 -0
  137. package/skills/istio/istio-authorization-policy-review/SKILL.md +44 -0
  138. package/skills/istio/istio-authorization-policy-review/agents/openai.yaml +5 -0
  139. package/skills/istio/istio-authorization-policy-review/metadata.json +30 -0
  140. package/skills/istio/istio-authorization-policy-review/references/applicability.md +9 -0
  141. package/skills/istio/istio-authorization-policy-review/references/authentication-and-identity.md +21 -0
  142. package/skills/istio/istio-authorization-policy-review/references/evidence-boundary.md +33 -0
  143. package/skills/istio/istio-authorization-policy-review/references/negative-tests.md +15 -0
  144. package/skills/istio/istio-authorization-policy-review/references/official-sources.md +33 -0
  145. package/skills/istio/istio-authorization-policy-review/references/output-contract.md +21 -0
  146. package/skills/istio/istio-authorization-policy-review/references/policy-set-semantics.md +21 -0
  147. package/skills/istio/istio-authorization-policy-review/references/protocol-and-normalization.md +19 -0
  148. package/skills/istio/istio-authorization-policy-review/references/review-contract.json +284 -0
  149. package/skills/istio/istio-dataplane-diagnostics/SKILL.md +45 -0
  150. package/skills/istio/istio-dataplane-diagnostics/agents/openai.yaml +5 -0
  151. package/skills/istio/istio-dataplane-diagnostics/metadata.json +30 -0
  152. package/skills/istio/istio-dataplane-diagnostics/references/applicability.md +9 -0
  153. package/skills/istio/istio-dataplane-diagnostics/references/collection-and-offline-analysis.md +17 -0
  154. package/skills/istio/istio-dataplane-diagnostics/references/evidence-boundary.md +33 -0
  155. package/skills/istio/istio-dataplane-diagnostics/references/hypothesis-workflow.md +19 -0
  156. package/skills/istio/istio-dataplane-diagnostics/references/negative-tests.md +13 -0
  157. package/skills/istio/istio-dataplane-diagnostics/references/official-sources.md +33 -0
  158. package/skills/istio/istio-dataplane-diagnostics/references/output-contract.md +21 -0
  159. package/skills/istio/istio-dataplane-diagnostics/references/review-contract.json +284 -0
  160. package/skills/istio/istio-dataplane-diagnostics/references/signal-interpretation.md +15 -0
  161. package/skills/istio/istio-gateway-api-review/SKILL.md +45 -0
  162. package/skills/istio/istio-gateway-api-review/agents/openai.yaml +5 -0
  163. package/skills/istio/istio-gateway-api-review/metadata.json +30 -0
  164. package/skills/istio/istio-gateway-api-review/references/applicability.md +9 -0
  165. package/skills/istio/istio-gateway-api-review/references/attachment-graph.md +19 -0
  166. package/skills/istio/istio-gateway-api-review/references/conditions-and-freshness.md +15 -0
  167. package/skills/istio/istio-gateway-api-review/references/evidence-boundary.md +33 -0
  168. package/skills/istio/istio-gateway-api-review/references/negative-tests.md +12 -0
  169. package/skills/istio/istio-gateway-api-review/references/official-sources.md +33 -0
  170. package/skills/istio/istio-gateway-api-review/references/output-contract.md +21 -0
  171. package/skills/istio/istio-gateway-api-review/references/review-contract.json +284 -0
  172. package/skills/istio/istio-gateway-api-review/references/tls-and-boundaries.md +17 -0
  173. package/skills/istio/istio-live-policy-change/SKILL.md +45 -0
  174. package/skills/istio/istio-live-policy-change/agents/openai.yaml +7 -0
  175. package/skills/istio/istio-live-policy-change/metadata.json +29 -0
  176. package/skills/istio/istio-live-policy-change/references/applicability.md +9 -0
  177. package/skills/istio/istio-live-policy-change/references/approval-and-scope.md +17 -0
  178. package/skills/istio/istio-live-policy-change/references/evidence-boundary.md +33 -0
  179. package/skills/istio/istio-live-policy-change/references/execution-protocol.md +19 -0
  180. package/skills/istio/istio-live-policy-change/references/negative-tests.md +12 -0
  181. package/skills/istio/istio-live-policy-change/references/official-sources.md +27 -0
  182. package/skills/istio/istio-live-policy-change/references/output-contract.md +21 -0
  183. package/skills/istio/istio-live-policy-change/references/review-contract.json +284 -0
  184. package/skills/istio/istio-live-policy-change/references/rollback-and-verification.md +19 -0
  185. package/skills/istio/istio-review-routing/SKILL.md +45 -0
  186. package/skills/istio/istio-review-routing/agents/openai.yaml +5 -0
  187. package/skills/istio/istio-review-routing/metadata.json +26 -0
  188. package/skills/istio/istio-review-routing/references/aggregation-and-conflicts.md +15 -0
  189. package/skills/istio/istio-review-routing/references/applicability.md +9 -0
  190. package/skills/istio/istio-review-routing/references/evidence-boundary.md +33 -0
  191. package/skills/istio/istio-review-routing/references/live-handoff.md +11 -0
  192. package/skills/istio/istio-review-routing/references/negative-tests.md +11 -0
  193. package/skills/istio/istio-review-routing/references/official-sources.md +9 -0
  194. package/skills/istio/istio-review-routing/references/output-contract.md +21 -0
  195. package/skills/istio/istio-review-routing/references/review-contract.json +284 -0
  196. package/skills/istio/istio-review-routing/references/routing-table.md +18 -0
  197. package/skills/istio/istio-traffic-resilience-review/SKILL.md +45 -0
  198. package/skills/istio/istio-traffic-resilience-review/agents/openai.yaml +5 -0
  199. package/skills/istio/istio-traffic-resilience-review/metadata.json +30 -0
  200. package/skills/istio/istio-traffic-resilience-review/references/applicability.md +9 -0
  201. package/skills/istio/istio-traffic-resilience-review/references/evidence-boundary.md +33 -0
  202. package/skills/istio/istio-traffic-resilience-review/references/mirroring-and-faults.md +15 -0
  203. package/skills/istio/istio-traffic-resilience-review/references/negative-tests.md +14 -0
  204. package/skills/istio/istio-traffic-resilience-review/references/official-sources.md +33 -0
  205. package/skills/istio/istio-traffic-resilience-review/references/output-contract.md +21 -0
  206. package/skills/istio/istio-traffic-resilience-review/references/review-contract.json +284 -0
  207. package/skills/istio/istio-traffic-resilience-review/references/routing-and-weights.md +19 -0
  208. package/skills/istio/istio-traffic-resilience-review/references/timeouts-retries-and-capacity.md +21 -0
  209. package/skills/istio/istio-upgrade-readiness/SKILL.md +45 -0
  210. package/skills/istio/istio-upgrade-readiness/agents/openai.yaml +5 -0
  211. package/skills/istio/istio-upgrade-readiness/metadata.json +30 -0
  212. package/skills/istio/istio-upgrade-readiness/references/applicability.md +9 -0
  213. package/skills/istio/istio-upgrade-readiness/references/crds-extensions-and-rollback.md +17 -0
  214. package/skills/istio/istio-upgrade-readiness/references/evidence-boundary.md +33 -0
  215. package/skills/istio/istio-upgrade-readiness/references/inventory-and-support.md +17 -0
  216. package/skills/istio/istio-upgrade-readiness/references/negative-tests.md +13 -0
  217. package/skills/istio/istio-upgrade-readiness/references/official-sources.md +33 -0
  218. package/skills/istio/istio-upgrade-readiness/references/output-contract.md +21 -0
  219. package/skills/istio/istio-upgrade-readiness/references/review-contract.json +284 -0
  220. package/skills/istio/istio-upgrade-readiness/references/skew-and-order.md +19 -0
  221. package/tests/fixtures/README.md +1 -1
  222. package/tests/fixtures/istio-maestro-routing/expected/001-happy-ambient-mesh-review.json +6 -0
  223. package/tests/fixtures/istio-maestro-routing/expected/002-happy-authorization-policy-review.json +6 -0
  224. package/tests/fixtures/istio-maestro-routing/expected/003-happy-dataplane-diagnostics.json +6 -0
  225. package/tests/fixtures/istio-maestro-routing/expected/004-happy-gateway-api-review.json +6 -0
  226. package/tests/fixtures/istio-maestro-routing/expected/005-happy-traffic-resilience-review.json +6 -0
  227. package/tests/fixtures/istio-maestro-routing/expected/006-happy-upgrade-readiness.json +6 -0
  228. package/tests/fixtures/istio-maestro-routing/expected/adv-ambiguous.json +4 -0
  229. package/tests/fixtures/istio-maestro-routing/expected/adv-instruction-injection.json +6 -0
  230. package/tests/fixtures/istio-maestro-routing/expected/adv-liveguard-01-kubernetes-live-mesh-policy-guard.json +6 -0
  231. package/tests/fixtures/istio-maestro-routing/expected/adv-persona-replacement.json +6 -0
  232. package/tests/fixtures/istio-maestro-routing/expected/adv-secrets-bait.json +6 -0
  233. package/tests/fixtures/istio-maestro-routing/expected/live-create-authorization-policy.json +6 -0
  234. package/tests/fixtures/istio-maestro-routing/expected/live-istio-gateway-apply.json +6 -0
  235. package/tests/fixtures/istio-maestro-routing/expected/live-kubectl-file-apply.json +6 -0
  236. package/tests/fixtures/istio-maestro-routing/expected/live-label-peer-authentication.json +6 -0
  237. package/tests/fixtures/istio-maestro-routing/expected/live-multiline-patch.json +6 -0
  238. package/tests/fixtures/istio-maestro-routing/expected/live-qualified-plural-delete.json +6 -0
  239. package/tests/fixtures/istio-maestro-routing/expected/live-resource-first-apply.json +6 -0
  240. package/tests/fixtures/istio-maestro-routing/expected/live-set-peer-authentication.json +6 -0
  241. package/tests/fixtures/istio-maestro-routing/expected/negative-product-identification.json +4 -0
  242. package/tests/fixtures/istio-maestro-routing/expected/negative-review-apply-safety.json +6 -0
  243. package/tests/fixtures/istio-maestro-routing/inputs/001-happy-ambient-mesh-review.json +7 -0
  244. package/tests/fixtures/istio-maestro-routing/inputs/002-happy-authorization-policy-review.json +7 -0
  245. package/tests/fixtures/istio-maestro-routing/inputs/003-happy-dataplane-diagnostics.json +7 -0
  246. package/tests/fixtures/istio-maestro-routing/inputs/004-happy-gateway-api-review.json +7 -0
  247. package/tests/fixtures/istio-maestro-routing/inputs/005-happy-traffic-resilience-review.json +7 -0
  248. package/tests/fixtures/istio-maestro-routing/inputs/006-happy-upgrade-readiness.json +7 -0
  249. package/tests/fixtures/istio-maestro-routing/inputs/adv-ambiguous.json +7 -0
  250. package/tests/fixtures/istio-maestro-routing/inputs/adv-instruction-injection.json +7 -0
  251. package/tests/fixtures/istio-maestro-routing/inputs/adv-liveguard-01-kubernetes-live-mesh-policy-guard.json +7 -0
  252. package/tests/fixtures/istio-maestro-routing/inputs/adv-persona-replacement.json +7 -0
  253. package/tests/fixtures/istio-maestro-routing/inputs/adv-secrets-bait.json +7 -0
  254. package/tests/fixtures/istio-maestro-routing/inputs/live-create-authorization-policy.json +8 -0
  255. package/tests/fixtures/istio-maestro-routing/inputs/live-istio-gateway-apply.json +8 -0
  256. package/tests/fixtures/istio-maestro-routing/inputs/live-kubectl-file-apply.json +8 -0
  257. package/tests/fixtures/istio-maestro-routing/inputs/live-label-peer-authentication.json +8 -0
  258. package/tests/fixtures/istio-maestro-routing/inputs/live-multiline-patch.json +8 -0
  259. package/tests/fixtures/istio-maestro-routing/inputs/live-qualified-plural-delete.json +8 -0
  260. package/tests/fixtures/istio-maestro-routing/inputs/live-resource-first-apply.json +8 -0
  261. package/tests/fixtures/istio-maestro-routing/inputs/live-set-peer-authentication.json +8 -0
  262. package/tests/fixtures/istio-maestro-routing/inputs/negative-product-identification.json +8 -0
  263. package/tests/fixtures/istio-maestro-routing/inputs/negative-review-apply-safety.json +8 -0
  264. package/tests/fixtures/istio-maestro-routing/taxonomy.json +129 -0
  265. package/tests/fixtures/istio-review-evals/README.md +11 -0
  266. package/tests/fixtures/istio-review-evals/expected/AMB-01.json +24 -0
  267. package/tests/fixtures/istio-review-evals/expected/AMB-02.json +24 -0
  268. package/tests/fixtures/istio-review-evals/expected/AMB-03.json +24 -0
  269. package/tests/fixtures/istio-review-evals/expected/AMB-04.json +24 -0
  270. package/tests/fixtures/istio-review-evals/expected/AMB-05.json +24 -0
  271. package/tests/fixtures/istio-review-evals/expected/AMB-06.json +24 -0
  272. package/tests/fixtures/istio-review-evals/expected/AMB-07.json +24 -0
  273. package/tests/fixtures/istio-review-evals/expected/AUTH-01.json +24 -0
  274. package/tests/fixtures/istio-review-evals/expected/AUTH-02A.json +24 -0
  275. package/tests/fixtures/istio-review-evals/expected/AUTH-02B.json +24 -0
  276. package/tests/fixtures/istio-review-evals/expected/AUTH-03.json +24 -0
  277. package/tests/fixtures/istio-review-evals/expected/AUTH-04.json +24 -0
  278. package/tests/fixtures/istio-review-evals/expected/AUTH-05.json +24 -0
  279. package/tests/fixtures/istio-review-evals/expected/AUTH-06.json +24 -0
  280. package/tests/fixtures/istio-review-evals/expected/AUTH-07.json +24 -0
  281. package/tests/fixtures/istio-review-evals/expected/AUTH-08.json +24 -0
  282. package/tests/fixtures/istio-review-evals/expected/DIAG-01.json +24 -0
  283. package/tests/fixtures/istio-review-evals/expected/DIAG-02.json +24 -0
  284. package/tests/fixtures/istio-review-evals/expected/DIAG-03.json +24 -0
  285. package/tests/fixtures/istio-review-evals/expected/DIAG-04.json +24 -0
  286. package/tests/fixtures/istio-review-evals/expected/DIAG-05.json +24 -0
  287. package/tests/fixtures/istio-review-evals/expected/GATEWAY-01.json +24 -0
  288. package/tests/fixtures/istio-review-evals/expected/GATEWAY-02A.json +24 -0
  289. package/tests/fixtures/istio-review-evals/expected/GATEWAY-02B.json +24 -0
  290. package/tests/fixtures/istio-review-evals/expected/GATEWAY-03.json +24 -0
  291. package/tests/fixtures/istio-review-evals/expected/GATEWAY-04.json +24 -0
  292. package/tests/fixtures/istio-review-evals/expected/GATEWAY-05.json +24 -0
  293. package/tests/fixtures/istio-review-evals/expected/GUARD-01.json +24 -0
  294. package/tests/fixtures/istio-review-evals/expected/GUARD-02.json +24 -0
  295. package/tests/fixtures/istio-review-evals/expected/GUARD-03.json +24 -0
  296. package/tests/fixtures/istio-review-evals/expected/GUARD-04.json +24 -0
  297. package/tests/fixtures/istio-review-evals/expected/GUARD-05.json +24 -0
  298. package/tests/fixtures/istio-review-evals/expected/GUARD-06.json +24 -0
  299. package/tests/fixtures/istio-review-evals/expected/ROUTE-01.json +24 -0
  300. package/tests/fixtures/istio-review-evals/expected/ROUTE-02.json +24 -0
  301. package/tests/fixtures/istio-review-evals/expected/ROUTE-03.json +24 -0
  302. package/tests/fixtures/istio-review-evals/expected/ROUTE-04.json +24 -0
  303. package/tests/fixtures/istio-review-evals/expected/ROUTE-05.json +24 -0
  304. package/tests/fixtures/istio-review-evals/expected/SAFETY-01.json +24 -0
  305. package/tests/fixtures/istio-review-evals/expected/SAFETY-02.json +24 -0
  306. package/tests/fixtures/istio-review-evals/expected/TRAFFIC-01A.json +24 -0
  307. package/tests/fixtures/istio-review-evals/expected/TRAFFIC-01B.json +24 -0
  308. package/tests/fixtures/istio-review-evals/expected/TRAFFIC-02.json +24 -0
  309. package/tests/fixtures/istio-review-evals/expected/TRAFFIC-03.json +24 -0
  310. package/tests/fixtures/istio-review-evals/expected/TRAFFIC-04.json +24 -0
  311. package/tests/fixtures/istio-review-evals/expected/TRAFFIC-05.json +24 -0
  312. package/tests/fixtures/istio-review-evals/expected/TRAFFIC-06.json +24 -0
  313. package/tests/fixtures/istio-review-evals/expected/TRAFFIC-07.json +24 -0
  314. package/tests/fixtures/istio-review-evals/expected/UPGRADE-01.json +24 -0
  315. package/tests/fixtures/istio-review-evals/expected/UPGRADE-02A.json +24 -0
  316. package/tests/fixtures/istio-review-evals/expected/UPGRADE-02B.json +24 -0
  317. package/tests/fixtures/istio-review-evals/expected/UPGRADE-03.json +24 -0
  318. package/tests/fixtures/istio-review-evals/expected/UPGRADE-04.json +24 -0
  319. package/tests/fixtures/istio-review-evals/expected/UPGRADE-05.json +24 -0
  320. package/tests/fixtures/istio-review-evals/expected/UPGRADE-06.json +24 -0
  321. package/tests/fixtures/istio-review-evals/inputs/AMB-01.json +20 -0
  322. package/tests/fixtures/istio-review-evals/inputs/AMB-02.json +22 -0
  323. package/tests/fixtures/istio-review-evals/inputs/AMB-03.json +39 -0
  324. package/tests/fixtures/istio-review-evals/inputs/AMB-04.json +21 -0
  325. package/tests/fixtures/istio-review-evals/inputs/AMB-05.json +20 -0
  326. package/tests/fixtures/istio-review-evals/inputs/AMB-06.json +19 -0
  327. package/tests/fixtures/istio-review-evals/inputs/AMB-07.json +17 -0
  328. package/tests/fixtures/istio-review-evals/inputs/AUTH-01.json +27 -0
  329. package/tests/fixtures/istio-review-evals/inputs/AUTH-02A.json +22 -0
  330. package/tests/fixtures/istio-review-evals/inputs/AUTH-02B.json +19 -0
  331. package/tests/fixtures/istio-review-evals/inputs/AUTH-03.json +30 -0
  332. package/tests/fixtures/istio-review-evals/inputs/AUTH-04.json +23 -0
  333. package/tests/fixtures/istio-review-evals/inputs/AUTH-05.json +22 -0
  334. package/tests/fixtures/istio-review-evals/inputs/AUTH-06.json +22 -0
  335. package/tests/fixtures/istio-review-evals/inputs/AUTH-07.json +30 -0
  336. package/tests/fixtures/istio-review-evals/inputs/AUTH-08.json +21 -0
  337. package/tests/fixtures/istio-review-evals/inputs/DIAG-01.json +18 -0
  338. package/tests/fixtures/istio-review-evals/inputs/DIAG-02.json +14 -0
  339. package/tests/fixtures/istio-review-evals/inputs/DIAG-03.json +16 -0
  340. package/tests/fixtures/istio-review-evals/inputs/DIAG-04.json +16 -0
  341. package/tests/fixtures/istio-review-evals/inputs/DIAG-05.json +16 -0
  342. package/tests/fixtures/istio-review-evals/inputs/GATEWAY-01.json +29 -0
  343. package/tests/fixtures/istio-review-evals/inputs/GATEWAY-02A.json +21 -0
  344. package/tests/fixtures/istio-review-evals/inputs/GATEWAY-02B.json +17 -0
  345. package/tests/fixtures/istio-review-evals/inputs/GATEWAY-03.json +22 -0
  346. package/tests/fixtures/istio-review-evals/inputs/GATEWAY-04.json +22 -0
  347. package/tests/fixtures/istio-review-evals/inputs/GATEWAY-05.json +16 -0
  348. package/tests/fixtures/istio-review-evals/inputs/GUARD-01.json +19 -0
  349. package/tests/fixtures/istio-review-evals/inputs/GUARD-02.json +16 -0
  350. package/tests/fixtures/istio-review-evals/inputs/GUARD-03.json +16 -0
  351. package/tests/fixtures/istio-review-evals/inputs/GUARD-04.json +20 -0
  352. package/tests/fixtures/istio-review-evals/inputs/GUARD-05.json +16 -0
  353. package/tests/fixtures/istio-review-evals/inputs/GUARD-06.json +16 -0
  354. package/tests/fixtures/istio-review-evals/inputs/ROUTE-01.json +16 -0
  355. package/tests/fixtures/istio-review-evals/inputs/ROUTE-02.json +18 -0
  356. package/tests/fixtures/istio-review-evals/inputs/ROUTE-03.json +15 -0
  357. package/tests/fixtures/istio-review-evals/inputs/ROUTE-04.json +25 -0
  358. package/tests/fixtures/istio-review-evals/inputs/ROUTE-05.json +15 -0
  359. package/tests/fixtures/istio-review-evals/inputs/SAFETY-01.json +14 -0
  360. package/tests/fixtures/istio-review-evals/inputs/SAFETY-02.json +15 -0
  361. package/tests/fixtures/istio-review-evals/inputs/TRAFFIC-01A.json +23 -0
  362. package/tests/fixtures/istio-review-evals/inputs/TRAFFIC-01B.json +17 -0
  363. package/tests/fixtures/istio-review-evals/inputs/TRAFFIC-02.json +19 -0
  364. package/tests/fixtures/istio-review-evals/inputs/TRAFFIC-03.json +28 -0
  365. package/tests/fixtures/istio-review-evals/inputs/TRAFFIC-04.json +18 -0
  366. package/tests/fixtures/istio-review-evals/inputs/TRAFFIC-05.json +18 -0
  367. package/tests/fixtures/istio-review-evals/inputs/TRAFFIC-06.json +18 -0
  368. package/tests/fixtures/istio-review-evals/inputs/TRAFFIC-07.json +17 -0
  369. package/tests/fixtures/istio-review-evals/inputs/UPGRADE-01.json +19 -0
  370. package/tests/fixtures/istio-review-evals/inputs/UPGRADE-02A.json +23 -0
  371. package/tests/fixtures/istio-review-evals/inputs/UPGRADE-02B.json +17 -0
  372. package/tests/fixtures/istio-review-evals/inputs/UPGRADE-03.json +21 -0
  373. package/tests/fixtures/istio-review-evals/inputs/UPGRADE-04.json +16 -0
  374. package/tests/fixtures/istio-review-evals/inputs/UPGRADE-05.json +33 -0
  375. package/tests/fixtures/istio-review-evals/inputs/UPGRADE-06.json +17 -0
  376. package/tests/fixtures/istio-review-evals/manifest.json +337 -0
  377. package/tests/fixtures/runtime-semantics/README.md +3 -0
  378. package/tests/fixtures/runtime-semantics/RUNTIME-AMB-L7.json +35 -0
  379. package/tests/fixtures/runtime-semantics/RUNTIME-AUTH-EMPTY.json +33 -0
  380. package/tests/fixtures/runtime-semantics/RUNTIME-GATEWAY.json +35 -0
  381. package/tests/fixtures/runtime-semantics/RUNTIME-JWT.json +34 -0
  382. package/tests/fixtures/runtime-semantics/RUNTIME-MIGRATION.json +35 -0
  383. package/tests/fixtures/runtime-semantics/RUNTIME-MIRROR.json +33 -0
  384. package/tests/fixtures/runtime-semantics/RUNTIME-UPGRADE.json +34 -0
  385. package/tests/integration/rbac-pre-flight/guards/mesh-policy.sh +9 -2
  386. package/tests/istio-review-suite/test_contract.py +121 -0
  387. package/tests/istio-review-suite/test_evidence_facts.py +344 -0
  388. package/tests/validate-catalog.py +156 -0
  389. package/tests/validate-model-params.py +161 -0
  390. package/tests/validate-readme-counts.mjs +58 -2
  391. package/tests/validate-release-notes.mjs +35 -0
  392. package/skills/istio/istio-ambient-mesh-review/references/mcp-and-evidence.md +0 -59
  393. package/skills/istio/istio-ambient-mesh-review/references/workflow-and-output.md +0 -128
@@ -342,6 +342,154 @@ def validate_guarded_live_kubernetes_agents() -> None:
342
342
  )
343
343
 
344
344
 
345
+ # Adapter files that prove a harness actually ships, mapped to the `harnesses` value
346
+ # that must then be declared.
347
+ HARNESS_ADAPTER_FILES = {
348
+ "codex.toml": "codex",
349
+ "copilot.agent.md": "copilot",
350
+ "claude-code.agent.md": "claude-code",
351
+ "cursor.agent.md": "cursor",
352
+ "gemini.agent.md": "gemini",
353
+ "kiro-ide.agent.md": "kiro",
354
+ "kiro-cli.agent.json": "kiro",
355
+ }
356
+
357
+ # Kiro is the one harness whose single `harnesses` value covers TWO adapter files, and the
358
+ # exporter emits both. Collapsing them into one set member would let a half-shipped Kiro
359
+ # adapter pass: with only kiro-ide.agent.md present, `kiro` is still in the on-disk set, the
360
+ # declaration matches, and the export later fails on the missing kiro-cli.agent.json. So the
361
+ # pair is checked explicitly rather than through the collapsed mapping.
362
+ KIRO_REQUIRED_FILES = ("kiro-ide.agent.md", "kiro-cli.agent.json")
363
+
364
+
365
+ def validate_harness_declarations() -> None:
366
+ """Every agent's `harnesses` must match the adapters it ships AND the catalog entry.
367
+
368
+ Three independent failures, each of which has actually happened or was one edit away:
369
+
370
+ * UNDER-declared (adapter on disk, harness absent from `harnesses`) makes a shipped
371
+ adapter invisible to everything that filters on the catalog. ionos, ovhcloud, and
372
+ scaleway each shipped all seven adapter files while declaring only codex and
373
+ claude-code, so generate-cursor-plugin.mjs omitted 18 real cursor adapters and
374
+ generate-kiro-powers.mjs dropped three real Kiro Powers.
375
+
376
+ * OVER-declared (harness claimed, no adapter file) promises an install path that does
377
+ not exist, failing at the user's `vfa-export-agents` rather than here.
378
+
379
+ * CATALOG DRIFT (metadata.json and catalog/agents.json disagree). catalog/agents.json
380
+ has no full regenerator — only an upsert — so fixing metadata.json does NOT update
381
+ it, and the catalog is what every generator actually reads. Checking metadata
382
+ against disk alone would report success while the original user-facing breakage
383
+ remained. This is not hypothetical: resyncing those 18 catalog entries was a
384
+ separate manual step from fixing their metadata.
385
+ """
386
+ problems: list[str] = []
387
+
388
+ catalog_harnesses: dict[str, list] = {}
389
+ catalog_agents = load_json(ROOT / "catalog" / "agents.json")
390
+ if isinstance(catalog_agents, dict):
391
+ catalog_agents = catalog_agents.get("agents", [])
392
+ for entry in catalog_agents:
393
+ if isinstance(entry, dict) and entry.get("type") == "agent":
394
+ catalog_harnesses[entry["id"]] = entry.get("harnesses") or []
395
+
396
+ for metadata_path in sorted(ROOT.glob("agents/*/*/metadata.json")):
397
+ data = load_json(metadata_path)
398
+ agent_id = data.get("id", metadata_path.parent.name)
399
+ declared = set(data.get("harnesses") or [])
400
+ harness_dir = metadata_path.parent / "harnesses"
401
+ present_files = (
402
+ {entry.name for entry in harness_dir.iterdir() if entry.is_file()}
403
+ if harness_dir.is_dir()
404
+ else set()
405
+ )
406
+ on_disk = {
407
+ HARNESS_ADAPTER_FILES[name]
408
+ for name in present_files
409
+ if name in HARNESS_ADAPTER_FILES
410
+ }
411
+ # "other" is a catalog-only escape hatch with no adapter file of its own.
412
+ declared.discard("other")
413
+
414
+ if on_disk - declared:
415
+ problems.append(
416
+ f"{agent_id}: ships adapters for {sorted(on_disk - declared)} "
417
+ f"but does not declare them in harnesses"
418
+ )
419
+ if declared - on_disk:
420
+ problems.append(
421
+ f"{agent_id}: declares harnesses {sorted(declared - on_disk)} "
422
+ f"with no matching adapter file"
423
+ )
424
+
425
+ # Kiro's two adapter files are checked as a pair, not through the collapsed value.
426
+ kiro_missing = [f for f in KIRO_REQUIRED_FILES if f not in present_files]
427
+ if "kiro" in declared and kiro_missing:
428
+ problems.append(
429
+ f"{agent_id}: declares the kiro harness but is missing {sorted(kiro_missing)} "
430
+ f"— both Kiro adapter files are required"
431
+ )
432
+ if kiro_missing and len(kiro_missing) == 1:
433
+ problems.append(
434
+ f"{agent_id}: ships a partial Kiro adapter — has "
435
+ f"{sorted(set(KIRO_REQUIRED_FILES) - set(kiro_missing))}, missing {kiro_missing}"
436
+ )
437
+
438
+ # The catalog is what the generators read; metadata alone proves nothing about them.
439
+ if agent_id in catalog_harnesses:
440
+ if sorted(catalog_harnesses[agent_id]) != sorted(data.get("harnesses") or []):
441
+ problems.append(
442
+ f"{agent_id}: catalog/agents.json declares "
443
+ f"{sorted(catalog_harnesses[agent_id])} but metadata.json declares "
444
+ f"{sorted(data.get('harnesses') or [])} — resync the catalog entry"
445
+ )
446
+
447
+ assert_true(
448
+ not problems,
449
+ "harness declarations disagree with shipped adapters or the catalog:\n - "
450
+ + "\n - ".join(problems),
451
+ )
452
+
453
+
454
+ def validate_tui_provider_enum() -> None:
455
+ """Every catalog provider must have a variant in the vfa-tui `Provider` enum.
456
+
457
+ tools/vfa-tui deserializes catalog/agents.json into a serde enum with
458
+ `deny_unknown_fields`, so a provider the enum does not know makes the whole catalog
459
+ fail to load and the TUI unusable. A Rust test already asserts this — but CI's
460
+ vfa-tui workflow is path-filtered to `tools/vfa-tui/**` (see
461
+ .github/workflows/vfa-tui-ci.yml), so a catalog-only PR that adds a provider never
462
+ triggers it and merges green while leaving the TUI broken. CLAUDE.md documents that
463
+ trap and asks contributors to remember `cargo test`; this makes remembering
464
+ unnecessary, because `npm run validate` is not path-filtered.
465
+
466
+ Parsed, never executed: variant names are read with a regex and converted to the
467
+ kebab-case slugs serde produces via `rename_all`, plus any explicit `rename = "..."`.
468
+ """
469
+ enum_path = ROOT / "tools" / "vfa-tui" / "src" / "models" / "provider.rs"
470
+ if not enum_path.exists():
471
+ # The TUI is optional to the catalog's correctness; absence is not a catalog error.
472
+ return
473
+ source = enum_path.read_text(encoding="utf8")
474
+ variants = re.findall(r"^\s{4}([A-Z][A-Za-z0-9]*),\s*$", source, re.MULTILINE)
475
+ slugs = {re.sub(r"(?<!^)(?=[A-Z])", "-", v).lower() for v in variants}
476
+ slugs |= set(re.findall(r'rename\s*=\s*"([a-z0-9-]+)"', source))
477
+
478
+ providers = set()
479
+ for entry in load_json(ROOT / "catalog" / "agents.json"):
480
+ if isinstance(entry, dict) and entry.get("provider"):
481
+ providers.add(entry["provider"])
482
+
483
+ missing = sorted(providers - slugs)
484
+ assert_true(
485
+ not missing,
486
+ "catalog providers with no variant in tools/vfa-tui/src/models/provider.rs: "
487
+ + f"{missing}. The TUI deserializes catalog/agents.json with a strict enum, so "
488
+ + "the catalog will fail to load entirely. Add the variant (kebab-case serde) and "
489
+ + "run `cargo test` in tools/vfa-tui.",
490
+ )
491
+
492
+
345
493
  def main() -> int:
346
494
  errors: list[str] = []
347
495
  seen_ids: set[str] = set()
@@ -364,6 +512,14 @@ def main() -> int:
364
512
  validate_codex_harness_adapters()
365
513
  except AssertionError as exc:
366
514
  errors.append(str(exc))
515
+ try:
516
+ validate_harness_declarations()
517
+ except AssertionError as exc:
518
+ errors.append(str(exc))
519
+ try:
520
+ validate_tui_provider_enum()
521
+ except AssertionError as exc:
522
+ errors.append(str(exc))
367
523
  try:
368
524
  validate_markdown_agent_templates()
369
525
  except AssertionError as exc:
@@ -0,0 +1,161 @@
1
+ #!/usr/bin/env python3
2
+ """Gate: Cursor per-model parameter groups are accepted or rejected correctly.
3
+
4
+ `scripts/model-policy.mjs` accepts Cursor's documented per-model parameter
5
+ group appended to a model id in square brackets, e.g.
6
+
7
+ claude-opus-5[effort=high,context=300k]
8
+
9
+ The registry namespace pattern only shapes that group (a nested-quantifier
10
+ regex is rejected by the registry's own ReDoS guard), so the structure — the
11
+ documented keys, the key=value shape, and no duplicates — is enforced
12
+ semantically inside the script. `validate:model-policy` only runs `check`
13
+ against the committed policy, which exercises the accepting path alone; this
14
+ gate pins the rejecting paths too, so the semantic validation cannot quietly
15
+ stop working.
16
+
17
+ Every case runs through `set --dry-run`, which validates the resulting policy
18
+ without writing anything.
19
+ """
20
+
21
+ from __future__ import annotations
22
+
23
+ import json
24
+ import re
25
+ import subprocess
26
+ import sys
27
+ from pathlib import Path
28
+
29
+ REPO = Path(__file__).resolve().parent.parent
30
+ ENGINE = REPO / "scripts" / "model-policy.mjs"
31
+ POLICY_SCHEMA = REPO / "schemas" / "model-policy.schema.json"
32
+
33
+ # (model value, should_be_accepted, why)
34
+ CASES: list[tuple[str, bool, str]] = [
35
+ ("composer-2.5", True, "bare registered id, no parameter group"),
36
+ ("claude-opus-5[effort=high]", True, "single documented key"),
37
+ ("gpt-5.6-sol[effort=high,context=300k]", True, "two documented keys"),
38
+ ("composer-2[fast=false]", True, "the fast key, boolean-ish value"),
39
+ ("claude-opus-5[bogus=1]", False, "undocumented key"),
40
+ ("claude-opus-5[effort=high,bogus=1]", False, "one good key, one undocumented"),
41
+ ("claude-opus-5[effort]", False, "missing =value"),
42
+ ("claude-opus-5[=high]", False, "missing key"),
43
+ ("claude-opus-5[effort=]", False, "empty value"),
44
+ ("claude-opus-5[]", False, "empty parameter group"),
45
+ ("claude-opus-5[effort=high,effort=low]", False, "duplicate key"),
46
+ ("claude-opus-5[effort=high=low]", False, "two separators in one pair"),
47
+ ("claude-opus-5[effort=high,context=300k=x]", False, "two separators in the second pair"),
48
+ ("claude-opus-5[=]", False, "separator with neither key nor value"),
49
+ ("not-a-registered-model[effort=high]", False, "base id absent from the allowlist"),
50
+ ("claude-opus-5[a=1][b=2]", False, "two groups"),
51
+ ("claude-opus-5[effort=high]trailing", False, "group not at the end"),
52
+ ]
53
+
54
+
55
+ def pick_agent_id() -> str:
56
+ """An agent id that exists in the catalog, so the scope resolves."""
57
+ agents = json.loads((REPO / "catalog" / "agents.json").read_text(encoding="utf-8"))
58
+ if not agents:
59
+ raise SystemExit("ERROR: catalog/agents.json is empty; cannot scope the probe")
60
+ return sorted(a["id"] for a in agents)[0]
61
+
62
+
63
+ def accepted(agent_id: str, model: str) -> tuple[bool, str]:
64
+ proc = subprocess.run(
65
+ [
66
+ "node",
67
+ str(ENGINE),
68
+ "set",
69
+ "--scope",
70
+ f"agent={agent_id}",
71
+ "--harness",
72
+ "cursor",
73
+ "--model",
74
+ model,
75
+ "--dry-run",
76
+ ],
77
+ cwd=REPO,
78
+ capture_output=True,
79
+ text=True,
80
+ )
81
+ return proc.returncode == 0, (proc.stdout + proc.stderr).strip()
82
+
83
+
84
+ def schema_model_pattern() -> str:
85
+ """The `model` pattern the policy schema declares for a rule."""
86
+ schema = json.loads(POLICY_SCHEMA.read_text(encoding="utf-8"))
87
+ return schema["properties"]["rules"]["items"]["properties"]["model"]["pattern"]
88
+
89
+
90
+ def check_schema_agrees(accepted_models: list[str]) -> list[str]:
91
+ """The script and the schema must agree on what a rule may contain.
92
+
93
+ A non-dry-run `set` writes the model value straight into
94
+ `catalog/model-policy.json`. If the script accepts a value the schema's
95
+ `model` pattern rejects, every policy using it is invalid under its own
96
+ declared contract and a schema-aware consumer will refuse it — a mismatch
97
+ the script's own validator can never surface, which is why it is asserted
98
+ here rather than left to the engine.
99
+ """
100
+ problems: list[str] = []
101
+ pattern = schema_model_pattern()
102
+ compiled = re.compile(pattern)
103
+ for model in accepted_models:
104
+ if not compiled.match(model):
105
+ problems.append(
106
+ f"schemas/model-policy.schema.json rejects {model!r}, which "
107
+ f"scripts/model-policy.mjs accepts (schema pattern: {pattern})"
108
+ )
109
+ # Values from other harnesses must keep working under the same pattern.
110
+ for model in ("qwen3:32b", "anthropic/claude-sonnet-4.5", "gpt-5.5", "auto", "inherit"):
111
+ if not compiled.match(model):
112
+ problems.append(
113
+ f"schemas/model-policy.schema.json rejects {model!r}, a value other "
114
+ f"harnesses rely on (schema pattern: {pattern})"
115
+ )
116
+ return problems
117
+
118
+
119
+ def main() -> int:
120
+ agent_id = pick_agent_id()
121
+ failures: list[str] = []
122
+
123
+ for model, want_ok, why in CASES:
124
+ got_ok, output = accepted(agent_id, model)
125
+ if got_ok == want_ok:
126
+ verdict = "accepted" if got_ok else "rejected"
127
+ print(f"OK {verdict:8} {model} ({why})")
128
+ continue
129
+ wanted = "accepted" if want_ok else "rejected"
130
+ got = "accepted" if got_ok else "rejected"
131
+ failures.append(
132
+ f"{model!r} should have been {wanted} ({why}) but was {got}\n"
133
+ f" engine output: {output.splitlines()[-1] if output else '(none)'}"
134
+ )
135
+
136
+ # A rejection must say why, not just fail: an operator needs to know which
137
+ # key was wrong.
138
+ _, msg = accepted(agent_id, "claude-opus-5[bogus=1]")
139
+ if "bogus" not in msg or "parameter" not in msg:
140
+ failures.append(
141
+ "the rejection message for an undocumented key must name the key and "
142
+ f"mention the parameter group; got: {msg!r}"
143
+ )
144
+
145
+ failures.extend(check_schema_agrees([m for m, ok, _ in CASES if ok]))
146
+
147
+ if failures:
148
+ print("\nFAIL: model parameter-group validation drifted:", file=sys.stderr)
149
+ for f in failures:
150
+ print(f" - {f}", file=sys.stderr)
151
+ return 1
152
+
153
+ print(
154
+ f"\nOK: {len(CASES)} model parameter-group cases behave as documented, "
155
+ "and the policy schema accepts every value the script does"
156
+ )
157
+ return 0
158
+
159
+
160
+ if __name__ == "__main__":
161
+ sys.exit(main())
@@ -10,6 +10,8 @@
10
10
  * roles = number of keys under .roles in catalog/install-roles.json
11
11
  * rules = length of JSON array in catalog/rules.json
12
12
  * mcp = length of JSON array in catalog/mcp-references.json
13
+ * provider agents = metadata provider values under agents/
14
+ * domain skills = SKILL.md files under each skills/<domain>/ directory
13
15
  *
14
16
  * Run: node tests/validate-readme-counts.mjs
15
17
  */
@@ -45,19 +47,27 @@ function findFiles(dir, basename) {
45
47
 
46
48
  const skillFiles = findFiles(path.join(repoRoot, "skills"), "SKILL.md");
47
49
  const computedSkills = skillFiles.length;
50
+ const skillsPerDirectory = new Map();
51
+ for (const f of skillFiles) {
52
+ const directory = path.relative(path.join(repoRoot, "skills"), f).split(path.sep)[0];
53
+ skillsPerDirectory.set(directory, (skillsPerDirectory.get(directory) ?? 0) + 1);
54
+ }
48
55
 
49
56
  const agentMetaFiles = findFiles(path.join(repoRoot, "agents"), "metadata.json");
50
57
  const computedAgents = agentMetaFiles.length;
51
58
 
52
59
  const providerSet = new Set();
60
+ const agentsPerProvider = new Map();
53
61
  for (const f of agentMetaFiles) {
54
62
  try {
55
63
  const data = JSON.parse(fs.readFileSync(f, "utf8"));
56
64
  if (typeof data.provider === "string" && data.provider.length > 0) {
57
65
  providerSet.add(data.provider);
66
+ agentsPerProvider.set(data.provider, (agentsPerProvider.get(data.provider) ?? 0) + 1);
58
67
  }
59
- } catch {
60
- // malformed metadata — skip silently
68
+ } catch (error) {
69
+ process.stderr.write(`FAIL [readme-counts] malformed agent metadata ${f}: ${error.message}\n`);
70
+ process.exit(1);
61
71
  }
62
72
  }
63
73
  const computedProviders = providerSet.size;
@@ -126,6 +136,22 @@ const labelToKey = {
126
136
 
127
137
  const failures = [];
128
138
 
139
+ const requiredIstioMarkers = [
140
+ ["Istio agent provider", /<!--\s*count:provider:istio\s*-->\d+<!--\s*\/count\s*-->/g],
141
+ [
142
+ "Istio skill directory",
143
+ /<!--\s*count:skill-directory:istio\s*-->\d+<!--\s*\/count\s*-->/g,
144
+ ],
145
+ ];
146
+ for (const [label, marker] of requiredIstioMarkers) {
147
+ const occurrences = readme.match(marker)?.length ?? 0;
148
+ if (occurrences !== 1) {
149
+ failures.push(
150
+ `FAIL [readme-counts] README must contain exactly one ${label} count marker; found ${occurrences}`
151
+ );
152
+ }
153
+ }
154
+
129
155
  // Parse table rows: | Label | Number |
130
156
  // Tolerate extra whitespace around cell content.
131
157
  const tableRowRe = /\|\s*([^|]+?)\s*\|\s*(\d+)\s*\|/g;
@@ -161,6 +187,36 @@ while ((spanMatch = spanRe.exec(readme)) !== null) {
161
187
  }
162
188
  }
163
189
 
190
+ const providerSpanRe =
191
+ /<!--\s*count:provider:([a-z0-9-]+)\s*-->(\d+)<!--\s*\/count\s*-->/g;
192
+ while ((spanMatch = providerSpanRe.exec(readme)) !== null) {
193
+ const slug = spanMatch[1];
194
+ const shownValue = parseInt(spanMatch[2], 10);
195
+ const computedValue = agentsPerProvider.get(slug);
196
+ if (computedValue === undefined) {
197
+ failures.push(`FAIL [readme-counts] unknown agent provider marker: ${slug}`);
198
+ } else if (shownValue !== computedValue) {
199
+ failures.push(
200
+ `FAIL [readme-counts] provider ${slug}: README shows ${shownValue}, computed ${computedValue}`
201
+ );
202
+ }
203
+ }
204
+
205
+ const skillDirectorySpanRe =
206
+ /<!--\s*count:skill-directory:([a-z0-9-]+)\s*-->(\d+)<!--\s*\/count\s*-->/g;
207
+ while ((spanMatch = skillDirectorySpanRe.exec(readme)) !== null) {
208
+ const slug = spanMatch[1];
209
+ const shownValue = parseInt(spanMatch[2], 10);
210
+ const computedValue = skillsPerDirectory.get(slug);
211
+ if (computedValue === undefined) {
212
+ failures.push(`FAIL [readme-counts] unknown skill directory marker: ${slug}`);
213
+ } else if (shownValue !== computedValue) {
214
+ failures.push(
215
+ `FAIL [readme-counts] skill directory ${slug}: README shows ${shownValue}, computed ${computedValue}`
216
+ );
217
+ }
218
+ }
219
+
164
220
  // ---------------------------------------------------------------------------
165
221
  // Report
166
222
  // ---------------------------------------------------------------------------
@@ -0,0 +1,35 @@
1
+ import { createRequire } from "node:module";
2
+ import { generateNotes } from "@semantic-release/release-notes-generator";
3
+
4
+ const require = createRequire(import.meta.url);
5
+ const config = require("../.releaserc.js");
6
+ const pluginConfig = config.plugins.find(
7
+ ([name]) => name === "@semantic-release/release-notes-generator",
8
+ )?.[1];
9
+
10
+ if (!pluginConfig) {
11
+ throw new Error("release-notes-generator configuration is missing");
12
+ }
13
+
14
+ const notes = await generateNotes(pluginConfig, {
15
+ commits: [
16
+ {
17
+ hash: "1234567890abcdef",
18
+ message: "feat(istio): add evidence-bounded review suite",
19
+ },
20
+ ],
21
+ lastRelease: { gitTag: "v3.11.1", gitHead: "old" },
22
+ nextRelease: { version: "3.12.0", gitTag: "v3.12.0", gitHead: "new" },
23
+ options: {
24
+ repositoryUrl:
25
+ "https://github.com/VincentChuWaiChow/vanguard-frontier-agentic.git",
26
+ },
27
+ cwd: process.cwd(),
28
+ logger: console,
29
+ });
30
+
31
+ if (!notes.includes("v3.12.0") || !notes.includes("evidence-bounded review suite")) {
32
+ throw new Error("release notes are missing the expected version or feature");
33
+ }
34
+
35
+ console.log("OK: semantic-release notes generated with the configured preset");
@@ -1,59 +0,0 @@
1
- # Evidence Path and Tooling
2
-
3
- ## Evidence path
4
-
5
- 1. Prefer live cluster evidence when a Kubernetes MCP server, `kubectl`, and `istioctl` are available against the mesh's primary cluster.
6
- 2. Fall back to the official Istio documentation (istio.io) for ambient/sidecar architecture, policy semantics, and CRD schema when live inspection is unavailable.
7
- 3. Ask only for sanitized YAML for the affected resources (`PeerAuthentication`, `AuthorizationPolicy`, `RequestAuthentication`, `Gateway`, `VirtualService`, `DestinationRule`, `Sidecar`, namespace labels) when current-state proof matters.
8
- 4. Label conclusions as `live evidence`, `documentation-based`, `sanitized user evidence`, or `inference`.
9
-
10
- ## Useful live-evidence commands
11
-
12
- ```shell
13
- # All Istio security and traffic policies across the cluster
14
- kubectl get peerauthentication,authorizationpolicy,requestauthentication,gateway,virtualservice,destinationrule,sidecar -A -o yaml
15
-
16
- # Confirm mesh mode (ambient vs sidecar) — namespace labels
17
- kubectl get namespaces --show-labels | grep -E 'istio.io/dataplane-mode|istio-injection'
18
-
19
- # Ambient: list waypoint deployments and bindings
20
- kubectl get gateways.gateway.networking.k8s.io -A -l istio.io/waypoint-for
21
- kubectl get pods -A -l gateway.networking.k8s.io/gateway-name
22
-
23
- # Inspect ztunnel state on each node
24
- kubectl -n istio-system get daemonset ztunnel
25
- istioctl x ztunnel-config workload # what ztunnel sees as in-mesh workloads
26
- istioctl x ztunnel-config policies # what L4 policies ztunnel is enforcing
27
- istioctl x ztunnel-config services # service-to-workload mapping
28
-
29
- # Validate proposed changes before applying
30
- istioctl analyze -n <namespace>
31
- istioctl analyze --recursive .
32
-
33
- # For sidecar mode: which workloads have sidecars injected
34
- kubectl get pods -A -o jsonpath='{range .items[?(@.metadata.annotations.sidecar\.istio\.io/inject!="false")]}{.metadata.namespace}/{.metadata.name}{"\n"}{end}'
35
-
36
- # Inspect effective policy at a specific workload
37
- istioctl proxy-config listener <pod>.<namespace>
38
- istioctl proxy-config cluster <pod>.<namespace>
39
- istioctl authz check <pod>.<namespace>
40
-
41
- # Mesh control-plane state
42
- kubectl -n istio-system get deploy istiod -o yaml
43
- istioctl version
44
- istioctl proxy-status
45
- ```
46
-
47
- ## Mesh state to confirm before review
48
-
49
- - **Mesh mode per namespace** — sidecar (`istio-injection=enabled`), ambient (`istio.io/dataplane-mode=ambient`), or none. A single mesh can mix modes; conclusions differ.
50
- - **Waypoint deployment for ambient namespaces** — `kubectl get gateways.gateway.networking.k8s.io -n <namespace> -l istio.io/waypoint-for`. Without a waypoint, L7 AuthorizationPolicy rules in that namespace are not enforced.
51
- - **Istio version** (`istioctl version`) — ambient went GA in 1.24; older versions have different semantics.
52
- - **Whether `PeerAuthentication` exists in the mesh root namespace** (default `istio-system` or whatever `meshConfig.rootNamespace` points to). Mesh-wide policies live there.
53
- - **Whether multi-cluster (multi-primary or primary-remote)** is in use — `AuthorizationPolicy` evaluation crosses cluster boundaries when mesh networking is configured.
54
-
55
- ## Sanitization rules
56
-
57
- - Never request kubeconfig contents, mesh root CA private keys, JWKs private keys, or workload service-account tokens.
58
- - Replace identifiable cluster URLs, JWT issuer URLs (when sensitive), and namespace names with placeholders unless the user provides them.
59
- - Do not print Istio root CA certificates beyond their public certificate body.
@@ -1,128 +0,0 @@
1
- # Workflow and Output Contract
2
-
3
- ## Workflow
4
-
5
- ### Step 1 — Identify mesh mode for the affected namespaces
6
-
7
- Istio supports three deployment modes that can coexist in one mesh. The review path differs based on mode.
8
-
9
- 1. **Sidecar mode** — pods have an Envoy sidecar injected. Namespace labeled `istio-injection=enabled`. All policy is enforced at the sidecar.
10
- 2. **Ambient mode** — no sidecars; ztunnel runs as a per-node DaemonSet for L4 zero-trust + optional waypoint proxies for L7. Namespace labeled `istio.io/dataplane-mode=ambient`.
11
- 3. **Mixed** — some workloads in a namespace use sidecars, others use ambient. Verify per-pod with annotations.
12
-
13
- Reference: [Choosing between sidecar and ambient](https://istio.io/latest/docs/overview/dataplane-modes/) and [Ambient mode overview](https://istio.io/latest/docs/ambient/overview/).
14
-
15
- ### Step 2 — Confirm waypoint deployment for ambient namespaces (the L7 trap)
16
-
17
- This is the most important ambient-specific check. Without a waypoint, L7 `AuthorizationPolicy` rules are silently ignored.
18
-
19
- 1. List waypoints: `kubectl get gateways.gateway.networking.k8s.io -n <namespace> -l istio.io/waypoint-for`.
20
- 2. Confirm the waypoint binding label on the namespace, ServiceAccount, or workload (`istio.io/use-waypoint: <waypoint-name>`).
21
- 3. Cross-reference any `AuthorizationPolicy` that uses L7 fields (`to.operation.methods`, `to.operation.paths`, `to.operation.hosts`, `when` keys for `request.headers`, `request.auth.claims`) — if no waypoint is bound to the workload, **the L7 rules are accepted by the API server but never enforced**.
22
-
23
- The L4 fields that ztunnel enforces without a waypoint:
24
-
25
- - `from.source.principals` (SPIFFE identities — the workload's ServiceAccount mTLS identity)
26
- - `from.source.namespaces`
27
- - `to.operation.ports`
28
- - `when` keys: `source.principal`, `source.namespace`, `destination.port`, `connection.sni`
29
-
30
- Reference: [L4 Authorization Policy in ambient](https://istio.io/latest/docs/ambient/usage/l4-policy/) and [Waypoint configuration](https://istio.io/latest/docs/ambient/usage/waypoint/).
31
-
32
- ### Step 3 — Audit `PeerAuthentication`
33
-
34
- `PeerAuthentication` controls workload-to-workload mTLS. Three modes exist with very different security properties:
35
-
36
- 1. **`STRICT`** — all peer connections must use mTLS. Plaintext connections are rejected. Production target.
37
- 2. **`PERMISSIVE`** — accepts both mTLS and plaintext. Useful only during migration.
38
- 3. **`DISABLE`** — disables mTLS. Plaintext only.
39
-
40
- Stress-tests:
41
-
42
- - **Mesh-wide PeerAuthentication** lives in the mesh root namespace (default `istio-system`). A change here affects every workload in every namespace simultaneously. Treat as critical-blast-radius.
43
- - **Namespace-scoped PeerAuthentication** with `mode: PERMISSIVE` in production is a finding — there is no migration in progress; this is technical debt.
44
- - **Workload-scoped PeerAuthentication** with `mode: DISABLE` for a specific port (e.g., a health-check port) is sometimes legitimate but always requires justification.
45
- - A namespace with **no `PeerAuthentication`** inherits mesh-wide. If mesh-wide is `PERMISSIVE`, the namespace is also `PERMISSIVE`.
46
-
47
- Reference: [PeerAuthentication API](https://istio.io/latest/docs/reference/config/security/peer_authentication/).
48
-
49
- ### Step 4 — Audit `AuthorizationPolicy`
50
-
51
- `AuthorizationPolicy` controls who can talk to whom. Default action when no policy exists is **ALLOW** — there is no implicit deny. Zero-trust requires explicit deny policies or explicit narrow ALLOW policies that combine to leave nothing reachable by default.
52
-
53
- Three actions: `ALLOW`, `DENY`, `CUSTOM`, `AUDIT`.
54
-
55
- 1. **`DENY` policies are evaluated first**, then `ALLOW`. If multiple match, DENY wins.
56
- 2. **Empty `rules` with `action: DENY`** denies everything — total lockdown.
57
- 3. **`action: ALLOW` with no `from` block** allows from anywhere — only useful for narrowing by `to`.
58
- 4. **`action: ALLOW` with `from.source.principals: ['*']`** is also "anywhere" — no practical narrowing.
59
-
60
- Stress-tests:
61
-
62
- - An `AuthorizationPolicy` with `action: ALLOW` and `from.source.namespaces: ['*']` is a documentation-only deny — it allows all and denies none.
63
- - L7 fields (`to.operation.methods`, `request.auth.claims`) in ambient mode without a waypoint are silently bypassed.
64
- - `action: AUDIT` is a logging-only mode that does not enforce — use only for migration.
65
- - Multi-cluster mesh: `AuthorizationPolicy` in one cluster can affect workloads called from another cluster; verify mesh networking topology.
66
-
67
- Reference: [AuthorizationPolicy API](https://istio.io/latest/docs/reference/config/security/authorization-policy/).
68
-
69
- ### Step 5 — Audit `RequestAuthentication`
70
-
71
- `RequestAuthentication` defines JWT validation — `jwksUri`, `issuer`, `audiences`, `forwardOriginalToken`. Key concerns:
72
-
73
- 1. **JWKs URI rotation** — if the issuer rotates signing keys, Istio caches the JWKs response. The `jwksUri` URL must remain reachable; outages here cause every JWT to fail.
74
- 2. **`forwardOriginalToken: true`** with sensitive JWTs forwards the bearer token to backend services — they must be trusted.
75
- 3. **`audiences: []` or missing** — accepts JWTs intended for any audience. Cross-service token replay risk.
76
- 4. **Multiple `RequestAuthentication` for the same workload** — Istio combines them. A misconfigured second one can weaken a strict first one.
77
-
78
- Reference: [RequestAuthentication API](https://istio.io/latest/docs/reference/config/security/request_authentication/).
79
-
80
- ### Step 6 — Audit `Gateway`, `VirtualService`, `DestinationRule`, `Sidecar`
81
-
82
- Traffic routing concerns:
83
-
84
- - **`Gateway` with `tls.mode: SIMPLE` and no `credentialName`** — broken or insecure TLS termination.
85
- - **`Gateway` with `tls.mode: PASSTHROUGH`** plus L7 routing in `VirtualService` — incompatible (passthrough cannot be inspected).
86
- - **`VirtualService.http.route` with `weight`-based traffic split** — verify total weights sum to 100; otherwise traffic is dropped.
87
- - **`DestinationRule.trafficPolicy.tls.mode: DISABLE`** on production destinations — disables Istio-side mTLS to the destination.
88
- - **`Sidecar` resource with `egress.hosts: ['*/*']`** — disables egress restriction.
89
-
90
- Reference: [Gateway API](https://istio.io/latest/docs/reference/config/networking/gateway/), [VirtualService API](https://istio.io/latest/docs/reference/config/networking/virtual-service/), [DestinationRule API](https://istio.io/latest/docs/reference/config/networking/destination-rule/), [Sidecar API](https://istio.io/latest/docs/reference/config/networking/sidecar/).
91
-
92
- ### Step 7 — Validate with `istioctl analyze`
93
-
94
- `istioctl analyze` runs the same checks the control plane runs and surfaces structural problems. Run it on the proposed YAML before applying:
95
-
96
- ```shell
97
- istioctl analyze -n <namespace> # one namespace
98
- istioctl analyze --all-namespaces # whole mesh
99
- istioctl analyze --recursive ./manifests/ # offline against files
100
- ```
101
-
102
- Common findings:
103
-
104
- - `IST0101` — referenced resource not found (e.g., `VirtualService` references a missing host).
105
- - `IST0118` — port name not following Istio's protocol convention (e.g., `tcp` vs `tcp-mysql`).
106
- - `IST0127` — namespace not labeled for injection.
107
-
108
- ## Output
109
-
110
- Return:
111
-
112
- - **target**: the resource and its scope (mesh-wide, namespace, workload),
113
- - **evidence level**: `live evidence` / `documentation-based` / `sanitized user evidence` / `inference`,
114
- - **mesh mode**: sidecar, ambient, or mixed for the affected workloads,
115
- - **waypoint state**: deployed and bound, missing, or not applicable (sidecar mode),
116
- - **L7 enforcement assessment**: whether L7 fields will actually run, with explicit "silently ignored" callouts where applicable,
117
- - **mTLS posture**: `STRICT` / `PERMISSIVE` / `DISABLE` per workload / namespace / mesh,
118
- - **risk findings** (with severity: high / medium / low),
119
- - **safest next actions** with sample manifest changes and `istioctl analyze` output,
120
- - **rollback plan**: how to revert the change without breaking mesh traffic mid-flight,
121
- - **assumptions and missing facts**.
122
-
123
- ## Security notes
124
-
125
- - Never recommend `PeerAuthentication` `mode: PERMISSIVE` or `DISABLE` for production without a documented mTLS migration plan with a date.
126
- - Never recommend a mesh-wide root-namespace policy change without staged rollout (single namespace first, observe, expand).
127
- - Never recommend disabling waypoint enforcement for an ambient namespace if any L7 `AuthorizationPolicy` exists for that namespace.
128
- - Do not print Istio root CA private keys or JWKs private keys.