@polymorphism-tech/morph-spec 8.33.0 → 8.35.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 (253) hide show
  1. package/CLAUDE.md +22 -2
  2. package/README.md +2 -2
  3. package/bin/morph-spec.js +43 -5
  4. package/claude-plugin.json +1 -1
  5. package/docs/CHEATSHEET.md +5 -4
  6. package/docs/QUICKSTART.md +1 -1
  7. package/framework/CLAUDE.md +2 -2
  8. package/framework/MORPH.md +20 -22
  9. package/framework/agents.json +198 -44
  10. package/framework/ai-pin.json +22 -0
  11. package/framework/commands/morph-media.md +45 -0
  12. package/framework/docs/CLI.md +238 -10
  13. package/framework/evals/proof-rubrics/README.md +76 -0
  14. package/framework/evals/proof-rubrics/eval-de-modelo.md +64 -0
  15. package/framework/evals/proof-rubrics/fiacao.md +54 -0
  16. package/framework/evals/proof-rubrics/guard-cego.md +52 -0
  17. package/framework/evals/proof-rubrics/media-claims.md +109 -0
  18. package/framework/evals/proof-rubrics/mutation-proof.md +77 -0
  19. package/framework/evals/proof-rubrics/observabilidade-genai.md +119 -0
  20. package/framework/evals/proof-rubrics/verde-nao-e-coberto.md +48 -0
  21. package/framework/evals/rubrics/architecture.md +30 -0
  22. package/framework/evals/rubrics/code-quality.md +26 -0
  23. package/framework/evals/rubrics/test-coverage.md +20 -0
  24. package/framework/hooks/README.md +11 -1
  25. package/framework/hooks/claude-code/core/block-destructive-worktree-removal.js +5 -8
  26. package/framework/hooks/claude-code/core/block-raw-worktree-add.js +79 -0
  27. package/framework/hooks/claude-code/core/chain.js +27 -7
  28. package/framework/hooks/claude-code/core/protect-spec-files.js +41 -4
  29. package/framework/hooks/claude-code/core/worktree-context.js +83 -14
  30. package/framework/hooks/claude-code/core/worktree-create.js +206 -0
  31. package/framework/hooks/claude-code/core/worktree-env-inject.js +87 -0
  32. package/framework/hooks/claude-code/core/worktree-remove.js +81 -0
  33. package/framework/hooks/shared/command-tokens.js +23 -0
  34. package/framework/hooks/shared/e2e-check.js +0 -0
  35. package/framework/hooks/shared/git-paths.js +25 -0
  36. package/framework/hooks/shared/hook-response.js +17 -0
  37. package/framework/hooks/shared/morph-cli.js +134 -0
  38. package/framework/rules/ai-agents-standards.md +14 -2
  39. package/framework/rules/infrastructure-standards.md +3 -1
  40. package/framework/schemas/ai-pin.schema.json +97 -0
  41. package/framework/schemas/config.schema.json +107 -0
  42. package/framework/schemas/feature.schema.json +23 -4
  43. package/framework/skills/core/create-umbraco-lp/SKILL.md +1 -1
  44. package/framework/skills/core/migrate-lp-to-umbraco/SKILL.md +1 -1
  45. package/framework/skills/core/morph-apply/SKILL.md +28 -7
  46. package/framework/skills/core/morph-brainstorming/SKILL.md +1 -1
  47. package/framework/skills/core/morph-eval/SKILL.md +1 -1
  48. package/framework/skills/core/morph-hotfix/SKILL.md +2 -2
  49. package/framework/skills/core/morph-implement/SKILL.md +20 -2
  50. package/framework/skills/core/morph-media/SKILL.md +215 -0
  51. package/framework/skills/core/morph-plan/SKILL.md +38 -4
  52. package/framework/skills/core/morph-proposal/SKILL.md +1 -1
  53. package/framework/skills/core/morph-review/SKILL.md +166 -9
  54. package/framework/skills/core/morph-stack-scan/SKILL.md +1 -1
  55. package/framework/skills/core/morph-standards/SKILL.md +1 -1
  56. package/framework/skills/core/morph-uiux/SKILL.md +1 -1
  57. package/framework/standards/PROVENANCE.json +81 -3
  58. package/framework/standards/STANDARDS.json +1504 -830
  59. package/framework/standards/ai-agents/agent-archetypes.md +160 -0
  60. package/framework/standards/ai-agents/agent-session.md +256 -160
  61. package/framework/standards/ai-agents/agent-spec.md +196 -0
  62. package/framework/standards/ai-agents/batching.md +217 -193
  63. package/framework/standards/ai-agents/context-providers.md +261 -188
  64. package/framework/standards/ai-agents/conversational-agent-with-phases.md +239 -0
  65. package/framework/standards/ai-agents/cost-and-budget.md +256 -0
  66. package/framework/standards/ai-agents/durable-workflows-hitl.md +98 -5
  67. package/framework/standards/ai-agents/evals-with-cache.md +289 -0
  68. package/framework/standards/ai-agents/guardrails.md +222 -0
  69. package/framework/standards/ai-agents/llm-runtime-defaults.md +226 -0
  70. package/framework/standards/ai-agents/mcp-server.md +351 -250
  71. package/framework/standards/ai-agents/mcp-tools.md +250 -197
  72. package/framework/standards/ai-agents/media-pipeline.md +352 -0
  73. package/framework/standards/ai-agents/media-video.md +267 -0
  74. package/framework/standards/ai-agents/middleware-patterns.md +241 -207
  75. package/framework/standards/ai-agents/modalities-image-gen.md +422 -173
  76. package/framework/standards/ai-agents/modalities-speech-to-text.md +177 -171
  77. package/framework/standards/ai-agents/modalities-text-to-speech.md +189 -181
  78. package/framework/standards/ai-agents/modalities-vision.md +205 -201
  79. package/framework/standards/ai-agents/multi-agent-patterns.md +211 -155
  80. package/framework/standards/ai-agents/observability-patterns.md +227 -17
  81. package/framework/standards/ai-agents/production.md +260 -231
  82. package/framework/standards/ai-agents/prompt-sources.md +389 -0
  83. package/framework/standards/ai-agents/providers/model-registry.md +293 -158
  84. package/framework/standards/ai-agents/rag-custom-pgvector.md +69 -4
  85. package/framework/standards/ai-agents/service-tier-flex.md +143 -135
  86. package/framework/standards/ai-agents/setup.md +166 -50
  87. package/framework/standards/ai-agents/structured-output.md +280 -249
  88. package/framework/standards/ai-agents/sweet-spot.md +129 -109
  89. package/framework/standards/ai-agents/testing-ai.md +236 -0
  90. package/framework/standards/ai-agents/vector-data-extensions.md +50 -20
  91. package/framework/standards/ai-agents/workflows.md +27 -7
  92. package/framework/standards/frontend/design-system/ai-image-generation.md +12 -0
  93. package/framework/standards/frontend/design-system/ai-video-generation.md +13 -0
  94. package/framework/standards/infrastructure/docker/local-compose-isolation.md +90 -0
  95. package/framework/templates/REGISTRY.json +14 -1
  96. package/framework/templates/code/dotnet/ai-agents/PromptRepository.cs.template +95 -95
  97. package/framework/templates/code/sql/ai-agents/agent-prompts-migration.sql.template +58 -58
  98. package/framework/templates/dotnet/ai-kit/Directory.Build.props +25 -0
  99. package/framework/templates/dotnet/ai-kit/Directory.Packages.props +26 -0
  100. package/framework/templates/dotnet/ai-kit/Morph.AiKit.sln +56 -0
  101. package/framework/templates/dotnet/ai-kit/NuGet.config +12 -0
  102. package/framework/templates/dotnet/ai-kit/README.md +128 -0
  103. package/framework/templates/dotnet/ai-kit/global.json +9 -0
  104. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Agents/AgentApi.cs +65 -0
  105. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Agents/AgentFactory.cs +289 -0
  106. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Agents/AgentFactoryOptions.cs +91 -0
  107. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Agents/AgentSpec.cs +91 -0
  108. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Agents/AgentSpecOptions.cs +181 -0
  109. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/AiKitAssemblyMarker.cs +14 -0
  110. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Conversation/ConversationStore.cs +174 -0
  111. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Conversation/IConversationStore.cs +54 -0
  112. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Conversation/InMemoryConversationStore.cs +75 -0
  113. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Evals/CountingChatClient.cs +71 -0
  114. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Evals/EvalAssertion.cs +246 -0
  115. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Evals/EvalCacheMissException.cs +57 -0
  116. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Evals/EvalCacheOptions.cs +78 -0
  117. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Evals/EvalCacheStamp.cs +225 -0
  118. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Evals/EvalFixture.cs +463 -0
  119. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Evals/EvalMode.cs +32 -0
  120. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Evals/EvalQualityEvaluators.cs +49 -0
  121. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Evals/EvalScenario.cs +214 -0
  122. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Evals/EvalSummary.cs +168 -0
  123. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Evals/OfflineChatClient.cs +142 -0
  124. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Evals/ShortPathResponseCache.cs +349 -0
  125. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/IMediaGenerator.cs +42 -0
  126. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/IMediaProvider.cs +77 -0
  127. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/MediaArtifact.cs +28 -0
  128. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/MediaDisclosure.cs +107 -0
  129. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/MediaGenerator.cs +253 -0
  130. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/MediaIdempotencyKey.cs +103 -0
  131. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/MediaJob.cs +259 -0
  132. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/MediaJobId.cs +21 -0
  133. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/MediaJobState.cs +47 -0
  134. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/MediaPricing.cs +102 -0
  135. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/MediaProvenance.cs +44 -0
  136. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/MediaRequest.cs +192 -0
  137. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/MediaResult.cs +94 -0
  138. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/MediaReview.cs +99 -0
  139. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/MediaSeams.cs +97 -0
  140. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/MediaStore.cs +133 -0
  141. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/MorphMedia.cs +93 -0
  142. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/Providers/GoogleImageProvider.cs +112 -0
  143. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/Providers/OpenAIImageProvider.cs +288 -0
  144. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/Providers/VeoVideoProvider.cs +158 -0
  145. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Middleware/IUsageCostSink.cs +29 -0
  146. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Middleware/UsageCostMiddleware.cs +208 -0
  147. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Middleware/UsageCostRecord.cs +95 -0
  148. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Morph.AiKit.csproj +38 -0
  149. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Observability/MorphOpenTelemetryExtensions.cs +119 -0
  150. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Observability/MorphTelemetryOptions.cs +82 -0
  151. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Providers/IProviderClientFactory.cs +33 -0
  152. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Providers/ModelAlias.cs +267 -0
  153. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Providers/ModelRegistry.cs +474 -0
  154. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Providers/model-registry.v2.json +87 -0
  155. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Rag/DeltaIngest.cs +169 -0
  156. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Rag/DeltaPlan.cs +49 -0
  157. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/AgentFactoryTests.cs +495 -0
  158. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/AgentSpecTests.cs +260 -0
  159. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/ConversationStoreTests.cs +405 -0
  160. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/DeltaIngestTests.cs +379 -0
  161. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Evals/EvalAssertionTests.cs +197 -0
  162. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Evals/EvalCacheMissTests.cs +139 -0
  163. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Evals/EvalCacheStampTests.cs +157 -0
  164. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Evals/EvalFailuresTests.cs +178 -0
  165. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Evals/EvalFixtureTests.cs +153 -0
  166. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Evals/EvalRefreshTests.cs +194 -0
  167. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Evals/EvalWorkspace.cs +86 -0
  168. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Evals/KitEvals.cs +213 -0
  169. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Evals/OfflineChatClientTests.cs +95 -0
  170. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Fakes/FakeChatClient.cs +225 -0
  171. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Fakes/FakeChatClientTests.cs +215 -0
  172. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Fakes/FakeClock.cs +33 -0
  173. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Fakes/FakeMediaProvider.cs +89 -0
  174. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Fakes/FakeProviderClientFactory.cs +55 -0
  175. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Fakes/FakeUsageCostSink.cs +60 -0
  176. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Fakes/InMemoryMediaStore.cs +131 -0
  177. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/MediaAccessibilityTests.cs +133 -0
  178. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/MediaAliasIsNotAnAgentTests.cs +127 -0
  179. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/MediaDisclosureTests.cs +216 -0
  180. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/MediaGeneratorTests.cs +264 -0
  181. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/MediaIdempotencyKeyTests.cs +148 -0
  182. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/MediaJobStateTests.cs +184 -0
  183. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/MediaReviewTests.cs +89 -0
  184. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/MediaStoreTests.cs +98 -0
  185. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/ModelRegistryTests.cs +451 -0
  186. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Morph.AiKit.Tests.csproj +76 -0
  187. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/SkeletonSmokeTests.cs +33 -0
  188. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/TelemetryTests.cs +261 -0
  189. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/UsageCostMiddlewareTests.cs +374 -0
  190. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/eval-cache/.morph-eval-cache.json +12 -0
  191. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/eval-cache/cache/orcamento.acme.a-resposta-estruturada/1/CF70A7CE27BBD66A/contents.data +13 -0
  192. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/eval-cache/cache/orcamento.acme.a-resposta-estruturada/1/CF70A7CE27BBD66A/entry.json +7 -0
  193. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/eval-cache/cache/triagem.acme.a-saudacao/1/19F631228C6E00BA/contents.data +13 -0
  194. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/eval-cache/cache/triagem.acme.a-saudacao/1/19F631228C6E00BA/entry.json +7 -0
  195. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/eval-cache/cache/triagem.acme.b-escalonamento/1/A24A7C9BDD8239D8/contents.data +13 -0
  196. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/eval-cache/cache/triagem.acme.b-escalonamento/1/A24A7C9BDD8239D8/entry.json +7 -0
  197. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/eval-cache/cache/triagem.globex.a-saudacao/1/E38CD37DF003EDB7/contents.data +13 -0
  198. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/eval-cache/cache/triagem.globex.a-saudacao/1/E38CD37DF003EDB7/entry.json +7 -0
  199. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/eval-datasets/orcamento/acme/a-resposta-estruturada.json +24 -0
  200. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/eval-datasets/triagem/acme/a-saudacao.json +23 -0
  201. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/eval-datasets/triagem/acme/b-escalonamento.json +24 -0
  202. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/eval-datasets/triagem/globex/a-saudacao.json +23 -0
  203. package/framework/templates/infrastructure/docker/docker-compose.template.yml +24 -14
  204. package/package.json +3 -3
  205. package/src/commands/e2e/e2e.js +91 -40
  206. package/src/commands/project/doctor.js +143 -6
  207. package/src/commands/project/env.js +95 -0
  208. package/src/commands/project/update.js +469 -153
  209. package/src/commands/project/worktree.js +274 -53
  210. package/src/commands/state/advance.js +24 -2
  211. package/src/commands/state/approve.js +33 -1
  212. package/src/commands/state/create.js +72 -11
  213. package/src/commands/state/delete.js +8 -0
  214. package/src/commands/state/finish.js +360 -53
  215. package/src/commands/state/gate-check.js +190 -6
  216. package/src/commands/state/score.js +36 -1
  217. package/src/commands/validation/verify.js +134 -25
  218. package/src/core/state/state-manager.js +9 -1
  219. package/src/dashboard/app/pages/HookInspector.jsx +430 -418
  220. package/src/dashboard/scanner/hooks-scanner.js +5 -1
  221. package/src/lib/ai/ai-checks.js +182 -0
  222. package/src/lib/ai/ai-project-scan.js +347 -0
  223. package/src/lib/ai/code-audit.js +181 -0
  224. package/src/lib/ai/comment-stripper.js +184 -0
  225. package/src/lib/ai/pin-drift.js +138 -0
  226. package/src/lib/ai/registry-audit.js +285 -0
  227. package/src/lib/e2e/compose-env.js +55 -14
  228. package/src/lib/e2e/stack-teardown.js +115 -0
  229. package/src/lib/evaluator-report.js +269 -15
  230. package/src/lib/generators/architecture-scanner.js +2 -1
  231. package/src/lib/git/default-branch.js +92 -4
  232. package/src/lib/graph/graphifyignore.js +2 -1
  233. package/src/lib/installers/effects.js +193 -0
  234. package/src/lib/installers/templates-reconcile.js +3 -3
  235. package/src/lib/risk-detector.js +284 -0
  236. package/src/lib/standards/verified-against.js +276 -0
  237. package/src/lib/tasks/eval-node.js +485 -0
  238. package/src/lib/tasks/linux-runner.js +297 -0
  239. package/src/lib/tasks/test-nodes.js +486 -0
  240. package/src/lib/tasks/test-runner.js +431 -37
  241. package/src/lib/validators/verify-runner.js +590 -28
  242. package/src/lib/worktree/dirs.js +32 -0
  243. package/src/lib/worktree/docker-audit.js +287 -0
  244. package/src/lib/worktree/env-allocator.js +69 -11
  245. package/src/lib/worktree/worktree-audit.js +70 -3
  246. package/src/scripts/setup-infra.js +24 -11
  247. package/src/utils/agents-installer.js +18 -8
  248. package/src/utils/claude-md-injector.js +10 -5
  249. package/src/utils/file-copier.js +28 -16
  250. package/src/utils/hooks-installer.js +75 -29
  251. package/src/utils/skills-installer.js +194 -187
  252. package/src/utils/version-checker.js +68 -3
  253. package/framework/standards/ai-agents/prompts-in-db.md +0 -214
@@ -1,109 +1,129 @@
1
- # Sweet Spot — When to use what in MAF
2
-
3
- > **Scope:** stacks=["dotnet"]
4
- > **Layer:** 0 (always-load via persona maf-expert)
5
- > **Keywords:** sweet spot, when to use agent, agent vs workflow, when not to use workflow, MAF decision, simple agent
6
- > **Read by Claude in:** plan (decide arquitetura da feature antes de quebrar em tasks) + implement (validar que a arquitetura ainda é a mais simples possível)
7
-
8
- **Verified against:** MAF Tier List research (2026-05-18) + Microsoft Learn docs. Last-verified: 2026-05-19.
9
-
10
- ---
11
-
12
- ## The 4-feature rule
13
-
14
- ```
15
- 95% of production AI agents need ONLY:
16
-
17
- 1. Chat (the LLM call)
18
- 2. Structured Output (typed records, not free text)
19
- 3. Tools (typed functions the agent can call)
20
- 4. RAG Custom (pgvector tool, not hosted RAG)
21
-
22
- If your feature needs ONLY these 4 → use a single agent. Don't reach for workflows.
23
- ```
24
-
25
- Apply this rule before deciding multi-agent or workflow. Most of the time the answer is "single agent".
26
-
27
- ---
28
-
29
- ## Decision tree (Claude reads this in plan phase)
30
-
31
- ```
32
- Step 1 — Does the task even need an LLM?
33
- ├─ "Can a deterministic function solve this?" → YES → write the function, no agent
34
- └─ NO → continue
35
-
36
- Step 2 — Single agent vs multi-agent?
37
- ├─ One topic + one decision → single agent (DEFAULT)
38
- ├─ Multiple specialized topics with clear handoff → multi-agent
39
- │ └─ Prefer Agent-as-Tool pattern (one agent uses another as a tool)
40
- │ └─ See ai-agents-multi-agent-patterns
41
- └─ "I'm not sure" → start with single agent, escalate if needed
42
-
43
- Step 3 — Need a Workflow?
44
- ├─ The feature has fan-in/out (many inputs aggregated) → maybe workflow
45
- │ └─ Confirm: can you write it as a foreach + LINQ aggregate?
46
- │ └─ YES → write the foreach, NO workflow
47
- │ └─ NO → workflow may help
48
- ├─ Long-running with human-in-the-loop checkpoints → maybe workflow
49
- │ └─ See ai-agents-workflows (Onda 2)
50
- └─ Otherwise → NO workflow
51
-
52
- Step 4 — Which provider?
53
- ├─ ALWAYS direct models — never a hosted agent service
54
- ├─ Provider choice (OpenAI / Google / Anthropic / Ollama) lives in the
55
- │ project's Model Registry, not hardcoded → see ai-agents-providers-model-registry
56
- └─ Hosted services (Foundry Agent Service, Vertex AI hosted) → NOT used
57
-
58
- Step 5 — RAG approach?
59
- ├─ Need control over chunking/embedding/storage? → RAG custom (pgvector)
60
- │ └─ See ai-agents-rag-custom-pgvector (Onda 2)
61
- └─ Don't reach for hosted RAG — loses control
62
- ```
63
-
64
- ---
65
-
66
- ## Anti-patterns (what Claude should NOT do)
67
-
68
- | Anti-pattern | Why it's wrong | What to do instead |
69
- |--------------|----------------|---------------------|
70
- | Reach for Workflow when a function does the job | "Tudo que Workflows fazem, código C# normal faz com menos complexidade" — pesquisa | Write the function. Wrap in a tool if an agent needs to call it. |
71
- | Use a hosted agent service | Hosted is "always 6-9 months behind" on models + removes control | Direct models always (OpenAI / Google / Anthropic / Ollama) |
72
- | Upload PDFs to a hosted RAG | Loses control of chunking + embedding + storage | Custom RAG with pgvector. See ai-agents-rag-custom-pgvector |
73
- | Add Memory/Session because "agents need state" | If not building a chatbot, don't add chat state | Skip. Add when a real chat UI exists. |
74
- | Use Semantic Kernel for new features | SK is superseded by MAF | Use Microsoft.Agents.AI. See ai-agents-setup |
75
- | Return free text and parse it downstream | LLM output is non-deterministic | Structured Output. See ai-agents-structured-output (Onda 2) |
76
-
77
- ---
78
-
79
- ## When the 4-feature rule does NOT apply
80
-
81
- You may need to step outside the sweet spot when:
82
- - The feature genuinely fans-out (e.g., monthly report aggregating N items) → workflow with fan-in
83
- - The feature needs vision/audio/image-gen → modality-specific standards (see ai-agents-modalities-* — Onda 3)
84
-
85
- **Even in these cases:** the core of the agent still follows the 4-feature rule. Only the orchestration layer changes.
86
-
87
- ---
88
-
89
- ## Checklist (verifiable by morph-eval)
90
-
91
- - [ ] Was each agent designed as single-agent BEFORE reaching for multi-agent? (Check `decisions.md`.)
92
- - [ ] If a Workflow is used, is fan-in/out or HITL checkpointing genuinely present? Or could `foreach + LINQ` replace it?
93
- - [ ] Are the 4 features (Chat, Structured Output, Tools, RAG Custom) all present where applicable?
94
- - [ ] Are hosted agent services avoided?
95
-
96
- ---
97
-
98
- ## References
99
-
100
- - `ai-agents-setup` — packages and DI
101
- - `ai-agents-providers-model-registry` — provider-agnostic config
102
- - `ai-agents-structured-output` (Onda 2)
103
- - `ai-agents-multi-agent-patterns` (Onda 2)
104
- - `ai-agents-workflows` (Onda 2, reframed)
105
- - `ai-agents-rag-custom-pgvector` (Onda 2)
106
-
107
- ---
108
-
109
- *MORPH-SPEC by Polymorphism Tech — ai-agents/sweet-spot.md v1.0 (2026-05-19)*
1
+ # Sweet Spot — When to use what in MAF
2
+
3
+ > **Scope:** stacks=["dotnet"]
4
+ > **Layer:** 0 (always-load via persona maf-expert)
5
+ > **Keywords:** sweet spot, when to use agent, agent vs workflow, when not to use workflow, MAF decision, simple agent, tool budget, quantas tools
6
+ > **Read by Claude in:** plan (decide arquitetura da feature antes de quebrar em tasks) + implement (validar que a arquitetura ainda é a mais simples possível)
7
+
8
+ **Verified against:** Microsoft.Agents.AI 1.20.0 + Microsoft.Agents.AI.Workflows 1.20.0 (ai-pin 2026-09-08 para o primeiro; o segundo está **fora do pin**, versão apurada no nuget.org em 2026-09-08). **Verificação documental**, sem cláusula `provado por` — este standard é decisão de arquitetura, não API. A escada de complexidade foi reconferida e **continua correta**; o que entrou de novo é o custo de definição de tool por turno e o status do Handoff. Last-verified: 2026-09-08.
9
+
10
+ ---
11
+
12
+ ## The 4-feature rule
13
+
14
+ ```
15
+ 95% of production AI agents need ONLY:
16
+
17
+ 1. Chat (the LLM call)
18
+ 2. Structured Output (typed records, not free text)
19
+ 3. Tools (typed functions the agent can call)
20
+ 4. RAG Custom (pgvector tool, not hosted RAG)
21
+
22
+ If your feature needs ONLY these 4 → use a single agent. Don't reach for workflows.
23
+ ```
24
+
25
+ Apply this rule before deciding multi-agent or workflow. Most of the time the answer is "single agent".
26
+
27
+ ### O quinto sinal: quantas tools o agente carrega
28
+
29
+ A regra das 4 features diz **o que** o agente faz. Falta **quanto** ele carrega — e esse é o custo que ninguém vê no código.
30
+
31
+ **Toda tool registrada entra na definição enviada ao modelo em CADA turno**: nome, descrição e o JSON Schema completo dos parâmetros. Um agente com 40 tools paga esses 40 schemas de entrada em todo turno, inclusive nos turnos em que nenhuma tool é chamada — e paga de novo em cada volta do laço de tool calling.
32
+
33
+ **Referência prática: ≤ 12 tools por agente.** Acima disso, dois efeitos se somam, e o segundo é pior que o primeiro:
34
+
35
+ 1. **Custo por turno cresce** com o tamanho da definição.
36
+ 2. **A escolha piora.** Quanto mais tools parecidas, mais o modelo erra qual chamar — e um erro de escolha custa uma volta inteira.
37
+
38
+ **Quando estourar o teto, na ordem:** (a) **poda** — remova o que não é usado naquele modo; (b) **plano por fase** — uma allow-list por estado do funil, montada em C# (`ai-agents-context-providers` §Ordem de escolha); (c) **só então** agent-as-tool, com o auxiliar carregando o próprio subconjunto (`ai-agents-multi-agent-patterns`). Servidor MCP com dezenas de tools é o caso mais comum de estouro — ver `ai-agents-mcp-tools` §Custo de definição de tool por turno.
39
+
40
+ ### Status do Handoff (2026-09-08)
41
+
42
+ O Handoff era marcado **experimental** no 1.0 e **graduou**: `Microsoft.Agents.AI.Workflows.HandoffWorkflowBuilder` **não carrega** `[Experimental]` na assembly 1.20.0 (medido). Isso muda o degrau da escada: handoff deixou de ser "experimental, evite" e passou a ser "estável, mas ainda depois de agent-as-tool" — a ordem de preferência **não** mudou, o motivo mudou. O critério continua o mesmo: agent-as-tool primeiro, handoff quando há N especialistas e a decisão de roteamento não cabe numa tool.
43
+
44
+ ---
45
+
46
+ ## Decision tree (Claude reads this in plan phase)
47
+
48
+ ```
49
+ Step 1 — Does the task even need an LLM?
50
+ ├─ "Can a deterministic function solve this?" → YES → write the function, no agent
51
+ └─ NO → continue
52
+
53
+ Step 2 — Single agent vs multi-agent?
54
+ ├─ One topic + one decision → single agent (DEFAULT)
55
+ ├─ Multiple specialized topics with clear handoff → multi-agent
56
+ │ └─ Prefer Agent-as-Tool pattern (one agent uses another as a tool)
57
+ │ └─ See ai-agents-multi-agent-patterns
58
+ └─ "I'm not sure" → start with single agent, escalate if needed
59
+
60
+ Step 3 — Need a Workflow?
61
+ ├─ The feature has fan-in/out (many inputs aggregated) → maybe workflow
62
+ │ └─ Confirm: can you write it as a foreach + LINQ aggregate?
63
+ │ └─ YES → write the foreach, NO workflow
64
+ │ └─ NO → workflow may help
65
+ ├─ Long-running with human-in-the-loop checkpoints → maybe workflow
66
+ │ └─ See ai-agents-workflows (Onda 2)
67
+ └─ Otherwise → NO workflow
68
+
69
+ Step 4 — Which provider?
70
+ ├─ ALWAYS direct models — never a hosted agent service
71
+ ├─ Provider choice (OpenAI / Google / Anthropic / Ollama) lives in the
72
+ │ project's Model Registry, not hardcoded → see ai-agents-providers-model-registry
73
+ └─ Hosted services (Foundry Agent Service, Vertex AI hosted) → NOT used
74
+
75
+ Step 5 — RAG approach?
76
+ ├─ Need control over chunking/embedding/storage? → RAG custom (pgvector)
77
+ │ └─ See ai-agents-rag-custom-pgvector (Onda 2)
78
+ └─ Don't reach for hosted RAG — loses control
79
+ ```
80
+
81
+ ---
82
+
83
+ ## Anti-patterns (what Claude should NOT do)
84
+
85
+ | Anti-pattern | Why it's wrong | What to do instead |
86
+ |--------------|----------------|---------------------|
87
+ | Reach for Workflow when a function does the job | "Tudo que Workflows fazem, código C# normal faz com menos complexidade" — pesquisa | Write the function. Wrap in a tool if an agent needs to call it. |
88
+ | Use a hosted agent service | Hosted is "always 6-9 months behind" on models + removes control | Direct models always (OpenAI / Google / Anthropic / Ollama) |
89
+ | Upload PDFs to a hosted RAG | Loses control of chunking + embedding + storage | Custom RAG with pgvector. See ai-agents-rag-custom-pgvector |
90
+ | Add Memory/Session because "agents need state" | If not building a chatbot, don't add chat state | Skip. Add when a real chat UI exists. |
91
+ | Use Semantic Kernel for new features | SK is superseded by MAF | Use Microsoft.Agents.AI. See ai-agents-setup |
92
+ | Return free text and parse it downstream | LLM output is non-deterministic | Structured Output. See ai-agents-structured-output (Onda 2) |
93
+
94
+ ---
95
+
96
+ ## When the 4-feature rule does NOT apply
97
+
98
+ You may need to step outside the sweet spot when:
99
+ - The feature genuinely fans-out (e.g., monthly report aggregating N items) → workflow with fan-in
100
+ - The feature needs vision/audio/image-gen → modality-specific standards (see ai-agents-modalities-* — Onda 3)
101
+
102
+ **Even in these cases:** the core of the agent still follows the 4-feature rule. Only the orchestration layer changes.
103
+
104
+ ---
105
+
106
+ ## Checklist (verifiable by morph-eval)
107
+
108
+ - [ ] Was each agent designed as single-agent BEFORE reaching for multi-agent? (Check `decisions.md`.)
109
+ - [ ] If a Workflow is used, is fan-in/out or HITL checkpointing genuinely present? Or could `foreach + LINQ` replace it?
110
+ - [ ] Are the 4 features (Chat, Structured Output, Tools, RAG Custom) all present where applicable?
111
+ - [ ] Are hosted agent services avoided?
112
+ - [ ] Nenhum agente carrega mais de ~12 tools sem uma decisão escrita em `decisions.md` sobre a poda
113
+
114
+ ---
115
+
116
+ ## References
117
+
118
+ - `ai-agents-setup` — packages and DI
119
+ - `ai-agents-providers-model-registry` — provider-agnostic config
120
+ - `ai-agents-structured-output` (Onda 2)
121
+ - `ai-agents-multi-agent-patterns` (Onda 2)
122
+ - `ai-agents-workflows` (Onda 2, reframed)
123
+ - `ai-agents-rag-custom-pgvector` (Onda 2)
124
+ - `ai-agents-mcp-tools` — o caso mais comum de estouro do teto de tools
125
+ - `ai-agents-context-providers` — plano por fase com allow-list de tools
126
+
127
+ ---
128
+
129
+ *MORPH-SPEC by Polymorphism Tech — ai-agents/sweet-spot.md v1.1 (2026-09-08)*
@@ -0,0 +1,236 @@
1
+ # Testing AI — como se testa um agente sem rede, sem chave e sem variância
2
+
3
+ > **Scope:** stacks=["dotnet"]
4
+ > **Layer:** 1 (on-keyword)
5
+ > **Keywords:** testar agente, fake IChatClient, ScriptedChatClient, harness de turno, eval de agente, teste sem rede, golden de prompt, compatibilidade binaria
6
+ > **Read by Claude in:** implement (ao escrever o teste de qualquer código que fala com um modelo)
7
+
8
+ **Verified against:** Microsoft.Extensions.AI 10.9.0 + Microsoft.Agents.AI 1.20.0 (ai-pin 2026-09-08); provado por `templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Fakes/FakeChatClient.cs` e `.../src/Morph.AiKit/Providers/IProviderClientFactory.cs` — o fake roteirizado e a costura que dispensa rede são o que o kit compila e exercita. Harness de turno completo e evals com cache de resposta são **verificação documental** — o ai-kit não os traz. Last-verified: 2026-09-08.
9
+
10
+ ---
11
+
12
+ ## Fronteira com o testing genérico
13
+
14
+ `backend-dotnet-testing` continua dono do que é de teste em .NET: xUnit, `FakeTimeProvider`,
15
+ isolamento entre casos, nomes de teste, organização de fixtures. **Nada disso se repete aqui.**
16
+
17
+ Este standard cobre **só o que é de agente** — e o que é de agente cabe em uma frase: o único ponto
18
+ em que o seu código toca um provider é um `IChatClient`. Todo o resto deste arquivo é consequência
19
+ disso.
20
+
21
+ ---
22
+
23
+ ## Fake de IChatClient
24
+
25
+ **Roteirizado e burro.** Uma fila de respostas escritas à mão, servidas na ordem:
26
+
27
+ - resposta de texto;
28
+ - resposta com chamada de função (`FunctionCallContent`);
29
+ - resposta de texto com uso preenchido (para exercitar a conta de custo).
30
+
31
+ A fila guarda **respostas**, não exceções: no exemplar do kit, os três métodos de enfileiramento
32
+ recebem `ChatResponse` (direto, por texto, ou por texto + uso), e o único `throw` do fake é o de
33
+ **fila esgotada**. Para exercitar o caminho de falha do provider, injete um cliente que lança em vez
34
+ de enfileirar uma exceção — são costuras diferentes, e confundi-las faz o teste de falha passar pelo
35
+ motivo errado.
36
+
37
+ E do outro lado, **captura**: as mensagens recebidas, as opções recebidas e a contagem de chamadas —
38
+ uma entrada por chamada, na ordem. É o que permite assertar *o que foi ao provedor*, e não apenas
39
+ *o que voltou*.
40
+
41
+ **A regra que define o padrão: o fake não pode ser inteligente.** Ele não escolhe resposta por
42
+ conteúdo, não simula um modelo, não "responde razoavelmente". E, esgotada a fila, **ele lança**, com
43
+ a contagem exata de chamadas. Devolver uma resposta vazia em silêncio faria um teste passar por
44
+ engano — que é a única coisa pior do que um teste falhando.
45
+
46
+ O argumento mais forte a favor desta forma não é teórico: **duas implementações independentes, em
47
+ dois produtos que não se conhecem, chegaram à mesma coisa** (um `FakeChatClient` e um
48
+ `ScriptedChatClient`, com a mesma fila e a mesma captura). O ai-kit compila a terceira.
49
+
50
+ ### A costura, e por que `sealed` não é desculpa para abri-la
51
+
52
+ O fake só serve se houver **um** ponto de injeção. No kit, esse ponto é uma interface de uma
53
+ operação — dado um alias resolvido, devolva o `IChatClient`. O registry permanece `sealed` e continua
54
+ sem saber construir cliente de provider nenhum.
55
+
56
+ > **O que o kit traz, e o que ele não traz.** A única implementação dessa interface no kit é a de
57
+ > **teste** (`FakeProviderClientFactory`) — medido. O adaptador de produção, aquele que faz o
58
+ > `switch` por provider e constrói o cliente de verdade, é **seu**: o kit prova que a costura
59
+ > funciona, não que o outro lado dela existe. É a mesma distinção de níveis do resto deste standard.
60
+
61
+ Precedente de campo com a **variante**: quando o registry é `sealed` e não se quer uma interface
62
+ pública, a costura foi um **construtor `internal`** recebendo uma função `alias -> IChatClient`,
63
+ exposta ao projeto de teste. As duas formas resolvem o mesmo problema; ambas preservam `sealed`, que
64
+ é a política da casa. **Costura de teste não é justificativa para tornar uma classe herdável.**
65
+
66
+ ---
67
+
68
+ ## Harness de turno
69
+
70
+ **Rode o loop real por cima do fake.** O valor não está em testar o fake; está em fazer o cliente de
71
+ invocação de funções **real** chamar as tools **reais**, com os clientes externos mockados.
72
+
73
+ É assim que se prova, sem rede e sem chave de API:
74
+
75
+ - que a tool escolhida foi a certa para aquele estado;
76
+ - que os argumentos montados batem;
77
+ - que o guard barrou o que devia barrar;
78
+ - que o teto de tool calls encerrou o turno onde devia;
79
+ - que o custo somou o que devia somar.
80
+
81
+ Nenhuma dessas cinco coisas é observável testando o compositor isolado — todas dependem do loop.
82
+
83
+ **Nota de ownership de recurso:** quem cria o cliente e quem o descarta precisa ser decidido uma vez.
84
+ Se a fábrica guardasse e reaproveitasse clientes por fora, existiriam duas caches da mesma coisa — e
85
+ duas caches da mesma coisa é como um cliente vazado sobrevive a um teste e polui o seguinte.
86
+
87
+ ---
88
+
89
+ ## Eval e unit
90
+
91
+ **"Eval" aqui não significa "modelo real".**
92
+
93
+ O padrão medido, e é o que dá mais retorno por hora escrita, é o **eval determinístico**: exercitar o
94
+ caminho **completo e real** — processador de turno, compositor, runner com middleware, tools,
95
+ persistência — com o comportamento do modelo **roteirizado**. Ganha-se cobertura de decisão sem
96
+ variância, e o teste falha por um motivo legível em vez de "o modelo respondeu diferente hoje".
97
+
98
+ Para o que **precisa** do modelo de verdade, o passo seguinte é uma biblioteca de avaliação com
99
+ **cache de resposta**, em **categoria própria** de teste — nunca misturada à suíte determinística. E
100
+ a regra que fecha: **gate duro só vale sobre propriedade determinística.** Reprovar um build porque
101
+ uma nota subjetiva caiu de 8,1 para 7,9 é transformar ruído em bloqueio.
102
+
103
+ **Zero chamada real ao provider dentro do `dotnet test`.** É uma propriedade **verificável
104
+ mecanicamente**, e o jeito de verificá-la é uma varredura sobre `tests/` procurando chave de
105
+ provider, leitura de variável de ambiente e cliente HTTP: ela precisa voltar **vazia**.
106
+
107
+ > **Quem faz essa varredura hoje: ninguém, automaticamente.** Medido em 2026-09-08 sobre o ai-kit
108
+ > (`grep -rniE "OPENAI_API_KEY|GetEnvironmentVariable|HttpClient|EnumerateFiles|Directory.Get"` em
109
+ > `templates/dotnet/ai-kit/**`): **zero ocorrências** — o que prova que o kit **não chama** o
110
+ > provider, e simultaneamente que **não existe teste que cobre essa ausência**. O kit descreve a
111
+ > propriedade em prosa (`FakeChatClient.cs`), não a guarda. Adotar esta regra significa **escrever a
112
+ > varredura no seu projeto**; herdá-la do kit é herdar uma intenção.
113
+
114
+ A medição de campo que sustenta a regra é do **acervo**, não do kit: `grep -c OPENAI_API_KEY` em
115
+ `tests/` = 0, sem nenhum teste marcado como pulado nem categoria de exclusão — ou seja, não há
116
+ "teste real desligado", há ausência de teste real.
117
+
118
+ **E o standard registra o preço disso**, porque ele é real: o harness com modelo de verdade daquele
119
+ projeto (onze cenários) **nunca foi rodado por completo ao vivo**. O que fica fora do `dotnet test`
120
+ tende a não rodar. Se um caminho precisa do modelo real, ele precisa de um dono e de um gatilho — ou
121
+ vai apodrecer.
122
+
123
+ ---
124
+
125
+ ## Captura do que foi ao provedor
126
+
127
+ O que se quer saber depois de um bug é: **o que exatamente foi enviado?**
128
+
129
+ Os dois artefatos que existem no campo, e nenhum deles se chama "captura da chamada crua":
130
+
131
+ 1. **As opções recebidas pelo fake** — em teste, é a prova direta de que a lista de tools ofertadas
132
+ saiu da lista real, de que o modo de tool era o esperado, e de que o esforço de raciocínio foi o
133
+ do alias.
134
+ 2. **O hash do texto que foi ao provedor** — em produção.
135
+
136
+ **A regra: prompt cru só em desenvolvimento e no harness, com opt-in explícito e sem dado pessoal;
137
+ em produção, hash.** Um prompt cru persistido em produção é um vazamento esperando indexação.
138
+
139
+ Duas asserções que o campo escreveu e que valem copiar: que a lista de tools ofertadas **saiu da
140
+ lista real** (e não de uma constante paralela), e que **turno cancelado não grava** — porque um
141
+ registro de algo que não aconteceu é pior que ausência de registro.
142
+
143
+ A metade de produção deste assunto — como o hash vira span, e a invariante que o torna confiável —
144
+ é de `ai-agents-observability-patterns`.
145
+
146
+ ---
147
+
148
+ ## Golden com parcimônia
149
+
150
+ Golden test congela uma saída em arquivo e compara. É excelente onde o **contrato é a forma**, e é
151
+ peso morto onde o conteúdo muda por motivo legítimo.
152
+
153
+ **Onde compensa:** o render de uma persona a partir de blocos, o contrato de saída estruturada, o
154
+ formato de um artefato publicado.
155
+
156
+ **Onde não compensa, com contra-exemplo real:** goldens de dois blobs de prompt foram **removidos de
157
+ propósito** de um projeto, com a justificativa medida — *"13,6 KB congelados para provar duas linhas
158
+ de concatenação"*. Cada edição de prompt exigia regravar 13,6 KB, o diff era ilegível, e a revisão
159
+ virava um "aceitar tudo". Um golden que ninguém lê no diff não é teste: é atrito.
160
+
161
+ O critério: **golden prova forma, não conteúdo.** Se a asserção real é "estas duas linhas
162
+ concatenam", escreva as duas linhas.
163
+
164
+ ### Teste de compatibilidade binária
165
+
166
+ Técnica, não filosofia: comparar em runtime a versão do assembly do SDK carregado com a que a ponte
167
+ referencia, e conferir a **assinatura** do membro que já quebrou uma vez. É barato, roda sem rede, e
168
+ pega a classe de defeito que custou uma chamada paga sem resposta. Ponte com
169
+ `ai-agents-llm-runtime-defaults`, seção de pin de SDK.
170
+
171
+ ### Prompt versionado é texto testável
172
+
173
+ Quando o prompt vive fora do código, ele continua sendo texto — e texto se testa. Ler a fonte
174
+ versionada e assertar:
175
+
176
+ - **presença** de uma regra que precisa estar lá;
177
+ - **vocabulário** das chaves que o consumidor espera;
178
+ - **ausência** de uma instrução revogada — que é a asserção que ninguém escreve e a que mais pega
179
+ regressão.
180
+
181
+ Precedente de campo: treze arquivos e cerca de 2.500 linhas fazendo exatamente isso. Ponte com
182
+ `ai-agents-prompt-sources`, seção de reconciliação.
183
+
184
+ ---
185
+
186
+ ## Anti-patterns
187
+
188
+ | Anti-pattern | Por quê é problema | Solução |
189
+ |---|---|---|
190
+ | Fake "inteligente" que escolhe resposta por conteúdo | Você passa a testar o fake | Fila roteirizada, servida na ordem |
191
+ | Fake que devolve vazio quando a fila acaba | O teste passa por engano | Lance, com a contagem de chamadas |
192
+ | Testar só o compositor, sem o loop real | Tool escolhida, guard e teto ficam sem cobertura | Harness com o cliente de invocação real |
193
+ | Chamada real ao provider dentro do `dotnet test` | Custo, flake e dependência de rede na suíte | Zero; e verifique com varredura |
194
+ | Harness com modelo real sem dono nem gatilho | Onze cenários que nunca rodaram por completo | Dono, gatilho e categoria própria |
195
+ | Gate duro sobre nota subjetiva de eval | Ruído virando bloqueio de build | Gate só sobre propriedade determinística |
196
+ | Prompt cru persistido em produção | Vazamento esperando indexação | Hash em produção; cru só em dev/harness com opt-in |
197
+ | Gravar telemetria de turno cancelado | Registro de algo que não aconteceu | Não grave |
198
+ | Golden de blob de prompt | 13,6 KB congelados para provar duas linhas | Asserte as duas linhas |
199
+ | Abrir a classe (`sealed` removido) para poder testar | Costura de teste virando decisão de arquitetura | Interface de uma operação, ou construtor `internal` |
200
+ | Fábrica que guarda e reaproveita clientes por fora | Duas caches da mesma coisa; cliente vazado entre testes | Ownership decidido num lugar |
201
+
202
+ ---
203
+
204
+ ## Checklist (verifiable by morph-eval)
205
+
206
+ - [ ] Existe um fake de `IChatClient` roteirizado, com captura de mensagens, opções e contagem
207
+ - [ ] O fake **lança** quando a fila acaba
208
+ - [ ] Há ao menos um teste que roda o loop **real** de invocação de funções por cima do fake
209
+ - [ ] Existe **no seu projeto** um teste que varre `tests/` por chave de provider, leitura de ambiente
210
+ e cliente HTTP, e ele volta vazio (o ai-kit **não** traz essa varredura — medido; herdá-la do
211
+ kit é herdar uma intenção)
212
+ - [ ] Nenhum teste real de modelo está apenas "pulado" — ou tem dono e gatilho, ou não existe
213
+ - [ ] Nenhum gate duro sobre nota subjetiva de eval
214
+ - [ ] Existe asserção de que a lista de tools ofertadas saiu da lista real
215
+ - [ ] Turno cancelado não grava telemetria
216
+ - [ ] Nenhum golden de blob de prompt; goldens existentes provam **forma**
217
+ - [ ] Existe teste de compatibilidade binária do par SDK × ponte
218
+ - [ ] O prompt versionado tem teste de texto, incluindo **ausência** de instrução revogada
219
+ - [ ] Nenhuma classe deixou de ser `sealed` por causa de teste
220
+
221
+ ---
222
+
223
+ ## References
224
+
225
+ - `backend-dotnet-testing` — dono do testing .NET genérico (xUnit, `FakeTimeProvider`, isolamento).
226
+ Nada dele se repete aqui
227
+ - `ai-agents-llm-runtime-defaults` — o pin de SDK que o teste de compatibilidade binária protege
228
+ - `ai-agents-prompt-sources` — a fonte versionada que o teste de prompt como texto lê
229
+ - `ai-agents-observability-patterns` — a metade de produção da captura (hash, span, invariante)
230
+ - `ai-agents-conversational-agent-with-phases` — compositor, allow-list e teto: o que o harness exercita
231
+ - `ai-agents-cost-and-budget` — a conta que o harness confere com uso roteirizado
232
+ - `ai-agents-guardrails` — os guards que só o loop real prova
233
+
234
+ ---
235
+
236
+ *MORPH-SPEC by Polymorphism Tech — ai-agents/testing-ai.md v1.0 (2026-09-08)*
@@ -5,7 +5,7 @@
5
5
  > **Keywords:** microsoft extensions vectordata, vectorstorecollection, vector store abstraction, data ingestion, ingestion pipeline, semantic kernel connectors exception, pgvector connector, vectorstorewriter
6
6
  > **Read by Claude in:** plan (when choosing a RAG storage backend) + implement (when deciding whether to adopt VectorData over custom pgvector)
7
7
 
8
- **Verified against:** Microsoft.Extensions.VectorData.Abstractions GA (`dotnet/extensions`, transferred from the Semantic Kernel repo) + Microsoft.Extensions.DataIngestion 10.0.1-preview.1.25571.5 + Microsoft.SemanticKernel.Connectors.PgVector 1.74.0-preview. Last-verified: 2026-07-06.
8
+ **Verified against:** Microsoft.Extensions.VectorData.Abstractions **10.9.0** + CommunityToolkit.VectorData.PgVector **1.0.1** + Microsoft.Extensions.DataIngestion **10.9.0-preview.1.26411.16** — nenhum deles está no `framework/ai-pin.json` (que cobre os 5 pacotes de agente), portanto **todas as versões acima foram apuradas na API do nuget.org em 2026-09-08** e são citadas com essa data, não como pin. **Verificação documental**, sem cláusula `provado por`: o ai-kit **não referencia nem exercita** VectorData — o pacote não está no `Morph.AiKit.csproj`, cujos cinco `PackageReference` são exatamente os do pin (medido 2026-09-08). Aqui nem a régua fraca do restore existe. Last-verified: 2026-09-08.
9
9
 
10
10
  ---
11
11
 
@@ -33,7 +33,23 @@ A single `VectorStoreCollection<TKey, TRecord>` shape works identically whether
33
33
 
34
34
  ## A pegadinha de nomenclatura (crítico — leia antes de tudo)
35
35
 
36
- The concrete vector-store **connectors** — the packages that actually implement `VectorStoreCollection` against a real backend — ship under `Microsoft.SemanticKernel.Connectors.*` package names (`Microsoft.SemanticKernel.Connectors.PgVector`, `.Qdrant`, `.SqlServer`, `.CosmosNoSQL`, `.InMemory`, etc.), even though `Microsoft.Extensions.VectorData.Abstractions` itself has been transferred out of the Semantic Kernel repo into `dotnet/extensions` and is fully independent of SK orchestration.
36
+ > **Atualização de 2026-09-08 — a pegadinha mudou de forma.** Os conectores concretos **saíram** dos nomes `Microsoft.SemanticKernel.Connectors.*` e passaram a `CommunityToolkit.VectorData.*` (repositório `github.com/CommunityToolkit/AI`). Medido na API do nuget.org em 2026-09-08:
37
+ >
38
+ > | Pacote | Última versão | Publicada | Estável? |
39
+ > |---|---|---|---|
40
+ > | `Microsoft.SemanticKernel.Connectors.PgVector` | `1.74.0-preview` | 2026-03-20 | **Nunca teve versão estável**; parou aí |
41
+ > | `CommunityToolkit.VectorData.PgVector` | **`1.0.1`** | **2026-08-31** | **Sim** |
42
+ > | `CommunityToolkit.VectorData.InMemory` | `1.0.1` | 2026-08-31 | Sim |
43
+ >
44
+ > Os dois carregam o **mesmo título e a mesma descrição** ("Postgres (with pgvector extension) provider for Microsoft.Extensions.VectorData"), trocando apenas o autor — *"by Semantic Kernel"* → *"by the .NET Community Toolkit"*. É a mesma peça, com outro dono e outro nome.
45
+ >
46
+ > **Use `CommunityToolkit.VectorData.PgVector` 1.0.1.** O pacote com nome de Semantic Kernel é caminho morto: última versão em março de 2026, e preview.
47
+ >
48
+ > *Fronteira do que foi medido:* a substituição acima é medida (existência, versões, datas, título e descrição, apurados na API do nuget.org em 2026-09-08). Que a página do NuGet **exiba um aviso de rename** não foi confirmado nem pelo `.nuspec` da 1.74.0-preview nem pelos metadados de deprecação da registration API — a afirmação aqui é a substituição, não o aviso.
49
+
50
+ A pegadinha original — abaixo — continua valendo para **projeto legado** que ainda referencia o nome antigo, e para quem tropeça no nome ao ler código existente.
51
+
52
+ The concrete vector-store **connectors** — the packages that actually implement `VectorStoreCollection` against a real backend — **used to** ship under `Microsoft.SemanticKernel.Connectors.*` package names (`Microsoft.SemanticKernel.Connectors.PgVector`, `.Qdrant`, `.SqlServer`, `.CosmosNoSQL`, `.InMemory`, etc.), even though `Microsoft.Extensions.VectorData.Abstractions` itself has been transferred out of the Semantic Kernel repo into `dotnet/extensions` and is fully independent of SK orchestration.
37
53
 
38
54
  Microsoft's own docs are explicit about this:
39
55
 
@@ -45,28 +61,36 @@ Microsoft's own docs are explicit about this:
45
61
 
46
62
  ## Maturidade atual (verificado 2026-07-06)
47
63
 
48
- | Package | Status |
49
- |---------|--------|
50
- | `Microsoft.Extensions.VectorData.Abstractions` | **GA** |
51
- | `Microsoft.Extensions.AI` / `Microsoft.Extensions.AI.Abstractions` | **GA** |
52
- | `Microsoft.SemanticKernel.Connectors.PgVector` (Postgres/pgvector connector) | **Prerelease** (1.74.0-preview, requires `--prerelease`) |
53
- | `Microsoft.SemanticKernel.Connectors.InMemory` / other connectors | Verify current status via context7/NuGet before adding — connector GA timing lags the abstractions package |
54
- | `Microsoft.Extensions.DataIngestion` | **Preview** (10.0.1-preview.1.25571.5) |
64
+ > Tabela **reapurada em 2026-09-08** na API do nuget.org. Cada linha traz a versão exata e a data — nenhum destes pacotes está no `framework/ai-pin.json`, então a data de apuração é o que dá validade ao número.
65
+
66
+ | Package | Versão (apurada 2026-09-08) | Status |
67
+ |---------|------------------------------|--------|
68
+ | `Microsoft.Extensions.VectorData.Abstractions` | **10.9.0** (publicada 2026-08-11) | **GA** — é a camada de abstração |
69
+ | `Microsoft.Extensions.AI` / `Microsoft.Extensions.AI.Abstractions` | **10.9.0** (no ai-pin) | **GA** |
70
+ | `CommunityToolkit.VectorData.PgVector` (Postgres/pgvector connector) | **1.0.1** (publicada 2026-08-31) | **Estável** — é o conector recomendado hoje |
71
+ | `CommunityToolkit.VectorData.InMemory` / demais conectores | **1.0.1** (2026-08-31) | Estável; confira cada um antes de adicionar |
72
+ | `Microsoft.SemanticKernel.Connectors.PgVector` | `1.74.0-preview` (2026-03-20) | **Caminho morto** — nunca teve versão estável e não avança desde março/2026 |
73
+ | `Microsoft.Extensions.DataIngestion` | **`10.9.0-preview.1.26411.16`** | **Preview** — sem versão estável |
55
74
 
56
- Preview packages are subject to breaking API changes before GA (see the May 2025 rename `PostgresVectorStoreRecordCollection` → `PostgresCollection` as precedent).
75
+ > **Cuidado com o número que o conector declara.** `CommunityToolkit.VectorData.PgVector` 1.0.1 depende de `Microsoft.Extensions.VectorData.Abstractions` **10.8.2** — esse é o **piso da dependência**, não a versão corrente da abstração, que é 10.9.0. Citar 10.8.2 como "a versão do VectorData" é ler o `.nuspec` do conector como se fosse o do pacote.
76
+
77
+ Preview packages are subject to breaking API changes before GA (see the rename `PostgresVectorStoreRecordCollection` → `PostgresCollection` as precedent).
57
78
 
58
79
  ---
59
80
 
60
81
  ## Decision matrix — custom pgvector vs VectorData
61
82
 
83
+ **O critério, em uma frase:** a abstração se paga quando **a troca de store é plausível**; o SQL cru se paga quando **já funciona e é testado**. Nada aqui manda migrar o que está de pé.
84
+
62
85
  | Situation | Use |
63
86
  |-----------|-----|
64
- | Default production RAG on Neon/Postgres (this framework's default stack) | **`ai-agents-rag-custom-pgvector`** — GA-quality, zero preview dependencies, framework-owned raw SQL, already the checklisted default |
65
- | Project needs genuine portability across >1 vector backend (e.g., a client contract requires swapping Postgres for Qdrant or Azure AI Search later) | `Microsoft.Extensions.VectorData` with the relevant connector — document the choice in `decisions.md` |
66
- | Prototyping, tests, or demos where an in-memory GA-quality store is enough | `Microsoft.Extensions.VectorData` + an in-memory/SQLite connector |
67
- | Team explicitly accepts a preview dependency for the Postgres connector today | Allowed, but record the acceptance + a revisit-at-GA note in `decisions.md`; do not silently swap the default |
87
+ | Default production RAG on Neon/Postgres (this framework's default stack), **already implemented and tested** | **`ai-agents-rag-custom-pgvector`** — framework-owned raw SQL, zero external connector, already the checklisted default. **Não se migra o que funciona** (item D4 da elevação-9) |
88
+ | **Projeto novo** onde a escolha do store ainda não foi cravada, e trocá-lo depois deve custar pouco | `Microsoft.Extensions.VectorData.Abstractions` 10.9.0 + `CommunityToolkit.VectorData.PgVector` 1.0.1 — hoje **ambos estáveis**, o que remove o argumento "é preview" que existia em julho/2026 |
89
+ | Project needs genuine portability across >1 vector backend (a client contract requires swapping Postgres for Qdrant or Azure AI Search later) | `Microsoft.Extensions.VectorData` + o conector correspondente — document the choice in `decisions.md` |
90
+ | Prototyping, tests, or demos where an in-memory store is enough | `CommunityToolkit.VectorData.InMemory` 1.0.1 |
91
+ | Ingestão em pipeline (reader → chunker → writer) hoje | Só com `Microsoft.Extensions.DataIngestion`, que **continua preview**: registre a aceitação e um lembrete de revisitar no GA |
68
92
 
69
- Do not migrate the existing `ai-agents-rag-custom-pgvector` implementation to the preview PgVector connector as a default — that would trade a working, GA-quality, framework-owned implementation for an unstable dependency, contradicting this framework's no-preview-by-default stance (see `ai-agents-setup` §1).
93
+ Do not migrate the existing `ai-agents-rag-custom-pgvector` implementation to VectorData as a default — that would rewrite a working, tested, framework-owned implementation for no functional gain. **O que mudou desde a verificação anterior:** o argumento *"o conector é preview"* **caiu** (o `CommunityToolkit` é estável desde 2026-08-31); o argumento *"não se reescreve o que funciona"* **permanece**, e é ele que sustenta o default hoje.
70
94
 
71
95
  ---
72
96
 
@@ -138,9 +162,11 @@ This maps conceptually onto the existing custom pattern: `IngestionDocumentReade
138
162
 
139
163
  | Anti-pattern | Why it's wrong | Right way |
140
164
  |--------------|----------------|-----------|
141
- | Refusing to add `Microsoft.SemanticKernel.Connectors.PgVector` because of the "Forbidden: Microsoft.SemanticKernel.*" rule | The rule targets SK orchestration, not VectorData connectors — see the naming-trap section above | Read this standard's exception note before treating any `Microsoft.SemanticKernel.Connectors.*` package as forbidden |
142
- | Migrating the working custom pgvector implementation to VectorData "because it's official" | The Postgres connector is still prerelease — trades a stable implementation for an unstable one with no functional gain by default | Keep `ai-agents-rag-custom-pgvector` as the default; adopt VectorData only per the decision matrix |
143
- | Treating `Microsoft.Extensions.DataIngestion` as production-ready | It ships as `10.0.1-preview.1` — breaking changes are expected before GA | Track it for future adoption; do not wire it into a shipped feature today |
165
+ | Refusing to add a VectorData connector because of the "Forbidden: Microsoft.SemanticKernel.*" rule | The rule targets SK orchestration, not VectorData connectors — see the naming-trap section above | Read this standard's exception note before treating any `Microsoft.SemanticKernel.Connectors.*` package as forbidden |
166
+ | **Adding `Microsoft.SemanticKernel.Connectors.PgVector` in a new project** | Caminho morto: `1.74.0-preview` de 2026-03-20, sem versão estável | `CommunityToolkit.VectorData.PgVector` 1.0.1 |
167
+ | **Citar `Microsoft.Extensions.VectorData.Abstractions` 10.8.2 como "a versão atual"** | 10.8.2 é o **piso da dependência** declarado pelo conector; a corrente é 10.9.0 | Ler a versão no pacote da abstração, não no `.nuspec` de quem depende dela |
168
+ | Migrating the working custom pgvector implementation to VectorData "because it's official" | Reescreve uma implementação testada sem ganho funcional. Note que o motivo mudou: já **não** é mais "porque é preview" | Keep `ai-agents-rag-custom-pgvector` as the default; adopt VectorData per the decision matrix |
169
+ | Treating `Microsoft.Extensions.DataIngestion` as production-ready | Continua preview em 2026-09-08 (`10.9.0-preview.1.26411.16`), sem versão estável | Track it for future adoption; do not wire it into a shipped feature today |
144
170
  | Importing `Microsoft.SemanticKernel` (the core orchestration package) to "just get the vector store types" | Pulls in the full SK orchestration surface this framework has deliberately moved away from | Import only `Microsoft.Extensions.VectorData.Abstractions` + the specific `*.Connectors.*` package needed |
145
171
 
146
172
  ---
@@ -150,7 +176,9 @@ This maps conceptually onto the existing custom pattern: `IngestionDocumentReade
150
176
  - [ ] If `Microsoft.SemanticKernel.Connectors.*` appears in a `.csproj`, it is used only for `VectorStoreCollection`/`VectorStore` types — no `Kernel`, `KernelFunction`, or `ChatHistory` usage anywhere in the project.
151
177
  - [ ] No plain `Microsoft.SemanticKernel` (core) package reference.
152
178
  - [ ] If VectorData was chosen over custom pgvector, the reason is recorded in `decisions.md` per the decision matrix.
153
- - [ ] If a preview package (`Microsoft.SemanticKernel.Connectors.*` or `Microsoft.Extensions.DataIngestion`) was adopted, `decisions.md` records the preview-acceptance and a revisit-at-GA note.
179
+ - [ ] No new `Microsoft.SemanticKernel.Connectors.*` reference — new work uses `CommunityToolkit.VectorData.*`.
180
+ - [ ] If a preview package (`Microsoft.Extensions.DataIngestion`, or any `*-preview` connector) was adopted, `decisions.md` records the preview-acceptance and a revisit-at-GA note.
181
+ - [ ] Every VectorData/ingestion `PackageReference` carries an exact version — these packages are **not** in `framework/ai-pin.json`, so the project's own `decisions.md` (or a comment) states when the version was checked.
154
182
  - [ ] Embedding model/dimensions consistent between the `VectorStoreVector(N)` attribute and the chosen embedding model.
155
183
 
156
184
  ---
@@ -164,7 +192,9 @@ This maps conceptually onto the existing custom pattern: `IngestionDocumentReade
164
192
  - Data ingestion - .NET | Microsoft Learn: https://learn.microsoft.com/en-us/dotnet/ai/conceptual/data-ingestion
165
193
  - AI and Vector Data Extensions GA announcement: https://devblogs.microsoft.com/dotnet/ai-vector-data-dotnet-extensions-ga/
166
194
  - Introducing Data Ingestion Building Blocks (Preview): https://devblogs.microsoft.com/dotnet/introducing-data-ingestion-building-blocks-preview/
195
+ - Vector stores overview: https://learn.microsoft.com/en-us/dotnet/ai/vector-stores/overview
196
+ - `CommunityToolkit.VectorData.*` — repositório https://github.com/CommunityToolkit/AI (apurado 2026-09-08)
167
197
 
168
198
  ---
169
199
 
170
- *MORPH-SPEC by Polymorphism Tech — ai-agents/vector-data-extensions.md v1.0 (2026-07-06)*
200
+ *MORPH-SPEC by Polymorphism Tech — ai-agents/vector-data-extensions.md v2.0 (2026-09-08)*