@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,173 +1,422 @@
1
- # Modalities — Image Generation (Text to Image)
2
-
3
- > **Scope:** stacks=["dotnet"]
4
- > **Layer:** 2 (on-keyword)
5
- > **Keywords:** image generation, text to image, dall-e, gpt-image, mockup generation, image synthesis
6
- > **Read by Claude in:** implement (quando o projeto precisa gerar imagens a partir de texto)
7
-
8
- **Verified against:** MAF 1.0 GA + OpenAI .NET SDK 2.x. Last-verified: 2026-05-19.
9
-
10
- ---
11
-
12
- ## Quando usar geração de imagem
13
-
14
- Use quando o produto precisa criar imagens em runtime a partir de um prompt textual:
15
-
16
- - **Mockups e protótipos visuais:** gerar capa de produto, banner de campanha, layout de tela
17
- - **Conteúdo para social media:** imagens para posts geradas a partir de briefing do usuário
18
- - **Visualizações:** diagramas, ilustrações ou thumbnails dinâmicos
19
-
20
- **Nota importante:** geração de imagem é uma **chamada de serviço ao provider**, não um agente conversacional. Não crie um `AIAgent` para isso — use `ImageClient` diretamente via DI.
21
-
22
- **Não use** quando um asset estático resolve o problema. Geração de imagem tem custo por chamada e latência de vários segundos. Se a imagem não muda por usuário/contexto, sirva de CDN.
23
-
24
- ---
25
-
26
- ## A API
27
-
28
- O projeto resolve o `ImageClient` para o provider configurado. No OpenAI SDK (.NET 2.x), o caminho é:
29
-
30
- ```csharp
31
- using OpenAI.Images;
32
-
33
- ImageClient client = new("dall-e-3", apiKey);
34
- GeneratedImage image = await client.GenerateImageAsync(prompt, options);
35
- ```
36
-
37
- O projeto injeta `ImageClient` via DI (ver §Exemplo). A resolução pode ser feita via factory ou diretamente por configuração — não há um `GetImageClient("alias")` no `ModelRegistry` padrão; registre o `ImageClient` como serviço nomeado ou use uma factory simples que lê `model-registry.json`.
38
-
39
- ---
40
-
41
- ## Exemplo C# completo
42
-
43
- ```csharp
44
- using OpenAI.Images;
45
- using Microsoft.Extensions.Configuration;
46
-
47
- public sealed class ImageGenerationService
48
- {
49
- private readonly ImageClient _client;
50
-
51
- public ImageGenerationService(IConfiguration config)
52
- {
53
- // O projeto configura o modelo e a chave via config/model-registry.json ou appsettings
54
- var model = config["ImageGen:Model"] ?? "dall-e-3";
55
- var apiKey = config["OpenAI:ApiKey"]!;
56
- _client = new ImageClient(model, apiKey);
57
- }
58
-
59
- /// <summary>
60
- /// Gera uma imagem a partir de um prompt e retorna os bytes PNG.
61
- /// Prefira armazenar os bytes; URLs retornadas pelo provider são efêmeras (expiram em ~1h).
62
- /// </summary>
63
- public async Task<BinaryData> GenerateImageBytesAsync(
64
- string prompt,
65
- GeneratedImageSize? size = null,
66
- GeneratedImageQuality? quality = null,
67
- CancellationToken ct = default)
68
- {
69
- var resolvedSize = size ?? GeneratedImageSize.W1024xH1024;
70
- var resolvedQuality = quality ?? GeneratedImageQuality.Standard;
71
-
72
- var options = new ImageGenerationOptions
73
- {
74
- Size = resolvedSize,
75
- Quality = resolvedQuality,
76
- ResponseFormat = GeneratedImageFormat.Bytes
77
- };
78
-
79
- GeneratedImage image = await _client.GenerateImageAsync(prompt, options, ct);
80
- return image.ImageBytes;
81
- }
82
-
83
- /// <summary>
84
- /// Gera uma imagem e retorna a URI. Use apenas quando precisar da URL diretamente
85
- /// e souber que o downstream vai consumir a URL antes de ela expirar (~1h no OpenAI).
86
- /// </summary>
87
- public async Task<Uri> GenerateImageUriAsync(string prompt, CancellationToken ct = default)
88
- {
89
- var options = new ImageGenerationOptions
90
- {
91
- Size = GeneratedImageSize.W1024xH1024,
92
- Quality = GeneratedImageQuality.Standard,
93
- ResponseFormat = GeneratedImageFormat.Uri
94
- };
95
-
96
- GeneratedImage image = await _client.GenerateImageAsync(prompt, options, ct);
97
- return image.ImageUri!;
98
- }
99
- }
100
- ```
101
-
102
- **Registro DI:**
103
-
104
- ```csharp
105
- // Program.cs
106
- builder.Services.AddSingleton<ImageGenerationService>();
107
- ```
108
-
109
- **Consumo:**
110
-
111
- ```csharp
112
- public class CampaignController(ImageGenerationService imageGen, IBlobStorage storage) : ControllerBase
113
- {
114
- [HttpPost("generate-banner")]
115
- public async Task<IActionResult> GenerateBanner([FromBody] BannerRequest req)
116
- {
117
- BinaryData bytes = await imageGen.GenerateImageBytesAsync(
118
- prompt: req.Briefing,
119
- size: GeneratedImageSize.W1792xH1024,
120
- quality: GeneratedImageQuality.High);
121
-
122
- // Persista no storage do projeto antes de retornar
123
- string storedUrl = await storage.UploadAsync(bytes, "image/png");
124
- return Ok(new { url = storedUrl });
125
- }
126
- }
127
- ```
128
-
129
- ---
130
-
131
- ## Parâmetros
132
-
133
- > Valores verificados contra OpenAI .NET SDK 2.x / DALL-E 3 (2026-05-19). Outros providers podem variar.
134
-
135
- | Parâmetro | Tipo | Opções | Nota |
136
- |-----------|------|--------|------|
137
- | `Size` | `GeneratedImageSize` | `W1024xH1024`, `W1792xH1024`, `W1024xH1792` | DALL-E 3 suporta os três; DALL-E 2 tem conjunto diferente |
138
- | `Quality` | `GeneratedImageQuality` | `Standard`, `High` | `High` = mais detalhe, mais custo e latência |
139
- | `Style` | `GeneratedImageStyle` | `Natural`, `Vivid` | `Vivid` = mais saturado/dramático; `Natural` = realista |
140
- | `ResponseFormat` | `GeneratedImageFormat` | `Bytes`, `Uri` | Prefira `Bytes` — URLs expiram em ~1h |
141
-
142
- ---
143
-
144
- ## Anti-patterns
145
-
146
- | Anti-pattern | Por quê é errado | Jeito certo |
147
- |--------------|-----------------|-------------|
148
- | Gerar imagem quando asset estático resolve | Custo por chamada + latência sem ganho | Sirva de CDN; só gere quando o conteúdo é dinâmico por usuário/contexto |
149
- | Não moderar o prompt antes de enviar | Prompts maliciosos podem gerar conteúdo impróprio; o provider rejeitará e você terá erro 400 sem log útil | Aplique validação/moderação de prompt antes de chamar `GenerateImageAsync`; veja `ai-agents-middleware-patterns` |
150
- | Armazenar a URI retornada sem baixar | URLs do provider são efêmeras (~1h no OpenAI); links quebram depois | Use `ResponseFormat = Bytes`, persista no storage do projeto e sirva sua própria URL |
151
- | Criar `AIAgent` para geração de imagem | `ImageClient` não é `IChatClient`; não há sentido em wrappear como agente | Injete `ImageGenerationService` diretamente — é um serviço, não um agente |
152
-
153
- ---
154
-
155
- ## Checklist (verifiable by morph-eval)
156
-
157
- - [ ] `ImageClient` injetado via DI — não instanciado inline nos controllers
158
- - [ ] `ResponseFormat = GeneratedImageFormat.Bytes` na maioria dos casos; URLs armazenadas no storage do projeto
159
- - [ ] Prompt passa por validação/moderação antes de ir ao provider
160
- - [ ] Não usa `AIAgent`/`AsAIAgent` para geração de imagem — é um `ImageGenerationService`
161
- - [ ] Model e API key vêm de config, não hardcoded
162
-
163
- ---
164
-
165
- ## References
166
-
167
- - `ai-agents-setup` — packages, DI, e providers disponíveis
168
- - `ai-agents-providers-model-registry` — padrão de alias; adapte para resolver `ImageClient` por provider
169
- - OpenAI .NET SDK — `ImageClient`: https://github.com/openai/openai-dotnet
170
-
171
- ---
172
-
173
- *MORPH-SPEC by Polymorphism Tech — ai-agents/modalities-image-gen.md v1.0 (2026-05-19)*
1
+ # Modalities — Image Generation (media-generation)
2
+
3
+ > **Scope:** stacks=["dotnet"]
4
+ > **Layer:** 2 (on-keyword)
5
+ > **Keywords:** image generation, text to image, gpt-image, nano banana, image editing, product photo, mockup generation, image synthesis
6
+ > **Read by Claude in:** implement (quando o projeto precisa gerar ou editar imagens em runtime)
7
+
8
+ **Verified against:** OpenAI 2.13.0 + Microsoft.Extensions.AI 10.9.0 + Google.GenAI 1.21.0 (ai-pin 2026-09-08); provado por `templates/dotnet/ai-kit/src/Morph.AiKit/Media/Providers/OpenAIImageProvider.cs` — `IImageGenerator`, `MEAI001`, `ImageGenerationRequest.OriginalImages` e a ausência de propriedade tipada para `quality` COMPILAM ali, e `OPENAI001` em `GeneratedImageQuality` foi medido pelo compilador. `HostedImageGenerationTool` foi medido por reflexão sobre a assembly do pin (existe, não é experimental); preço, data de desligamento e limites de referência são **verificação documental** contra as páginas de §Como re-verificar este standard. Last-verified: 2026-09-08.
9
+
10
+ ---
11
+
12
+ Geração de imagem **em runtime, a partir de .NET**. Autoria de asset de landing page por MCP, em
13
+ tempo de design, é outro standard e outro consumidor:
14
+ `frontend/design-system/ai-image-generation.md` — prompt craft de marca, `assets.md`, integração com
15
+ `next/image`. Este aqui é sobre a chamada paga que o seu backend faz, o que ela custa e onde ela
16
+ pode morar.
17
+
18
+ O pipeline que recebe o pedido, revisa e publica está em `ai-agents/media-pipeline.md`. Vídeo está
19
+ em `ai-agents/media-video.md`.
20
+
21
+ ---
22
+
23
+ ## Quando usar geração de imagem
24
+
25
+ | Caso | Por que a geração ganha do asset estático |
26
+ |---|---|
27
+ | **Catálogo** | Variação de tecido, cor e cena sobre o **mesmo** produto real, a partir de foto de referência |
28
+ | **Marketing** | Peça de campanha por segmento, com texto na imagem, em volume |
29
+ | **Variação de produto** | N combinações que ninguém fotografaria uma a uma |
30
+
31
+ **Não use** quando um asset estático resolve: custo por chamada, latência de vários segundos e
32
+ nenhuma garantia de repetibilidade. Se a imagem não muda por usuário ou por contexto, sirva de CDN.
33
+
34
+ **Não use dentro de um turno de conversa.** Esta é a regra dura da casa, e ela não é estética:
35
+ a documentação da própria OpenAI declara que um prompt complexo pode levar **até 2 minutos**, cada
36
+ chamada custa dinheiro, e dentro do turno **não existe revisão humana possível**. O turno enfileira
37
+ e confirma; a mídia volta depois, revisada. O mecanismo que prende essa regra — e não apenas a
38
+ explica — está em `ai-agents/media-pipeline.md`.
39
+
40
+ ---
41
+
42
+ ## A API
43
+
44
+ Duas superfícies, e a escolha entre elas é por **necessidade**, não por gosto.
45
+
46
+ ### Abstração `IImageGenerator` (Microsoft.Extensions.AI)
47
+
48
+ ```csharp
49
+ using Microsoft.Extensions.AI;
50
+ using OpenAI.Images;
51
+
52
+ #pragma warning disable MEAI001 // IImageGenerator e experimental: a superficie pode mudar entre menores
53
+ // AsIImageGenerator() vem de Microsoft.Extensions.AI.OpenAI — um pacote A MAIS.
54
+ // Sem ele, escreva o adaptador (e o kit escreve: ver a nota abaixo).
55
+ IImageGenerator generator = new ImageClient("gpt-image-2", apiKey).AsIImageGenerator();
56
+
57
+ var response = await generator.GenerateAsync(
58
+ new ImageGenerationRequest { Prompt = prompt },
59
+ new ImageGenerationOptions { MediaType = "image/png", Count = 1 },
60
+ ct);
61
+ #pragma warning restore MEAI001
62
+
63
+ var bytes = response.Contents.OfType<DataContent>().First().Data;
64
+ ```
65
+
66
+ > **A ponte é um pacote separado, e isso muda o seu `.csproj`.** `AsIImageGenerator()` é uma extensão
67
+ > de `Microsoft.Extensions.AI.OpenAI`; ter `Microsoft.Extensions.AI` e `OpenAI` **não** basta —
68
+ > medido pelo compilador. Se o pacote da ponte não estiver no seu pin, o caminho é escrever um
69
+ > `IImageGenerator` sobre o `ImageClient`, como o exemplar do kit faz em
70
+ > `templates/dotnet/ai-kit/src/Morph.AiKit/Media/Providers/OpenAIImageProvider.cs`. As duas
71
+ > alternativas são legítimas; o que não é legítimo é descobrir isso em tempo de build depois de ter
72
+ > escrito o pipeline inteiro.
73
+
74
+ Fatos que decidem o desenho, medidos contra `Microsoft.Extensions.AI.Abstractions` 10.9.0:
75
+
76
+ - `IImageGenerator` carrega `[Experimental("MEAI001")]`. Suprimir o diagnóstico é obrigatório, e o
77
+ `#pragma` **leva comentário do risco** — é o que separa "assumimos a instabilidade" de
78
+ "silenciamos um aviso".
79
+ - `ImageGenerationRequest` tem `Prompt` e `OriginalImages` (`IEnumerable<AIContent>`). `OriginalImages`
80
+ é o gancho de **edição com referência** — é por ele que o produto real é preservado.
81
+ - `ImageGenerationOptions` expõe `AdditionalProperties`, `Count`, `ImageSize`, `MediaType`,
82
+ `ModelId`, `RawRepresentationFactory`, `ResponseFormat` e `StreamingCount`. **Não há propriedade
83
+ tipada** para `quality`, `background` ou `input_fidelity`: esses vão por `AdditionalProperties` ou
84
+ por `RawRepresentationFactory`. Escrever `options.Quality` não compila, e procurar por ela é o
85
+ primeiro tropeço de quem chega vindo do `ImageClient` direto.
86
+ - Único adaptador oficial é OpenAI/Azure OpenAI (`OpenAIClientExtensions.AsIImageGenerator`, **no
87
+ pacote `Microsoft.Extensions.AI.OpenAI` — ver a ressalva acima**). Para
88
+ Gemini **não existe** adaptador MEAI oficial: use `Google.GenAI` direto
89
+ (`Client.Models.GenerateContentAsync` com `ResponseModalities = ["IMAGE", "TEXT"]`, lendo
90
+ `Candidates[0].Content.Parts[..].InlineData`), ou escreva um `IImageGenerator` próprio.
91
+
92
+ ### Images API direto, quando o produto real precisa ser preservado
93
+
94
+ `POST /v1/images/edits` aceita N imagens de referência (PNG/JPG/WebP, cada uma **abaixo de 50 MB**,
95
+ mesmo formato e tamanho) e uma `mask` PNG com alfa nas mesmas dimensões da primeira imagem. É o
96
+ caminho para catálogo: editar preserva; gerar do zero recria.
97
+
98
+ `GenerateImageVariationAsync` do SDK **não é opção** — a API de variações só existia no modelo
99
+ listado em §Deprecações.
100
+
101
+ ---
102
+
103
+ ## Tool hospedada de imagem
104
+
105
+ `Microsoft.Extensions.AI.HostedImageGenerationTool` existe na 10.9.0, **não** é experimental e é um
106
+ *marker*: ela não gera nada, apenas informa ao serviço que o modelo pode gerar
107
+ (`Name => "image_generation"`). O adaptador da OpenAI mapeia `ModelId → Model`,
108
+ `MediaType → OutputFileFormat`, `StreamingCount → PartialImageCount` e `ImageSize → Size`;
109
+ **`quality`, `background`, `moderation` e `input_fidelity` não são mapeados**. O resultado volta
110
+ como `ImageGenerationToolResultContent { Outputs = [DataContent] }` dentro de
111
+ `ChatResponse.Messages[..].Contents` — nunca como `FunctionResultContent`.
112
+
113
+ > **Procedência, separada em dois níveis.** Que o tipo **existe** e **não** é experimental na 10.9.0
114
+ > foi medido por reflexão sobre a assembly do pin. Já a **tabela de mapeamento** acima vem da leitura
115
+ > de `OpenAIResponsesChatClient.cs` em
116
+ > `https://github.com/dotnet/extensions/blob/main/src/Libraries/Microsoft.Extensions.AI.OpenAI/`,
117
+ > consultado em 2026-09-07 — é
118
+ > código **interno** da ponte, fora da superfície pública, e portanto não confirmável por reflexão.
119
+ > Confirme contra o provedor configurado antes de contar com um desses parâmetros pela tool.
120
+
121
+ **E é exatamente por isso que ela não entra no agente de WhatsApp.** A tool é o caminho natural de
122
+ "me mostra esse sofá em verde", e a documentação a descreve para chat/atendimento. Este standard
123
+ **contradiz** essa leitura para o atendimento, com o motivo escrito:
124
+
125
+ | Fato | Consequência no turno |
126
+ |---|---|
127
+ | Latência documentada de até 2 min | O turno estoura; o cliente vê silêncio |
128
+ | Custo por chamada, sem teto natural | Um usuário curioso vira uma fatura |
129
+ | `quality`/`moderation` não mapeados pelo adaptador | Você não controla nem o custo nem o filtro |
130
+ | Nenhuma revisão possível dentro do turno | Claim visual errado sai direto para o cliente |
131
+
132
+ O que o turno faz é **enfileirar e confirmar**. A tool hospedada é legítima em ferramenta interna,
133
+ com humano na frente da tela e orçamento controlado — nunca no canal do cliente.
134
+
135
+ ---
136
+
137
+ ## Provedor por alias
138
+
139
+ O alias mora no `model-registry.v2.json` do kit, com `api` declarando o protocolo. Alias de imagem
140
+ usa `api: images`; alias de vídeo, `api: videos` (ver `ai-agents/media-video.md`). O `AgentFactory`
141
+ **recusa com erro nomeado** um alias de mídia passado como agente de chat: um alias de imagem
142
+ resolvido como conversa apontaria para um modelo que não fala chat, e a falha apareceria tarde e
143
+ confusa.
144
+
145
+ | Papel | Alias | Por quê |
146
+ |---|---|---|
147
+ | Imagem, default | `gpt-image-2` | Default do próprio provedor; resolução arbitrária (múltiplos de 16 px, lado ≤ 3840 px, razão ≤ 3:1); até 8 imagens coerentes por prompt; `input_fidelity` deixou de existir porque a fidelidade já é alta |
148
+ | Imagem, referência de produto | `gemini-3.1-flash-image` | 10 objetos + 4 personagens + 3 estilos de referência — o caso "muitas fotos do mesmo móvel" |
149
+ | Imagem, lote barato | `gemini-3.1-flash-lite-image` | O piso de preço da família, com 14 objetos de referência |
150
+ | Vídeo | ver `ai-agents/media-video.md` | Fora do escopo deste standard |
151
+
152
+ **Nenhum alias fora desta lista sem passar pela tabela de §Deprecações primeiro.** Um alias
153
+ proibido não é preferência de estilo: é dinheiro gasto num endpoint que vai devolver erro.
154
+
155
+ ---
156
+
157
+ ## Prompt como spec versionada
158
+
159
+ Um prompt de produção é **template versionado**, nunca string concatenada no handler. O que o
160
+ template fixa:
161
+
162
+ 1. **Estrutura, sempre na mesma ordem:** cena/fundo → sujeito → detalhes-chave → restrições.
163
+ Segmentos rotulados; frases descritivas, não lista de keywords.
164
+ 2. **Fotorrealismo declarado** quando é o caso ("photorealistic", "professional product
165
+ photography"); termos de câmera servem à composição, não à física.
166
+ 3. **Texto na imagem entre aspas literais**, marcas soletradas.
167
+ 4. **"Preserve list" repetida em CADA iteração de edição** — "change only X, keep everything else".
168
+ Iterações pequenas e sequenciais; ao driftar, reinicie a conversa com a descrição completa em vez
169
+ de empilhar correções.
170
+ 5. **Fundo transparente vem do parâmetro, não do prompt** (`background=transparent` + PNG/WebP):
171
+ descrever o fundo no texto faz o prompt vencer o parâmetro.
172
+
173
+ O prompt final vai para a proveniência do job junto com o `revised_prompt` que o provedor devolve —
174
+ ver `ai-agents/media-pipeline.md`. Prompt que não foi gravado não pode ser reproduzido nem auditado.
175
+
176
+ Para prompt craft de marca (paleta, tom, herói aprovado como referência das derivadas), o standard
177
+ é `frontend/design-system/ai-image-generation.md`; este não o repete.
178
+
179
+ ---
180
+
181
+ ## Referências de produto
182
+
183
+ | Modelo | Limite de referência |
184
+ |---|---|
185
+ | `gemini-3.1-flash-lite-image` | 14 objetos |
186
+ | `gemini-3.1-flash-image` | 10 objetos + 4 personagens + 3 estilos |
187
+ | `gemini-3-pro-image` | 6 objetos + 5 personagens |
188
+ | OpenAI `/v1/images/edits` | N imagens, cada uma abaixo de 50 MB, mesmo formato e tamanho |
189
+
190
+ **Indexe cada referência no prompt** ("image 1 = o sofá; image 2 = o tecido") e diga como elas
191
+ interagem. Referência não nomeada é referência que o modelo escolhe sozinho como usar.
192
+
193
+ O hash sha256 de cada referência entra na chave de idempotência do pedido (`media-pipeline.md`):
194
+ trocar a foto de referência **é** outro pedido, mesmo com o prompt idêntico.
195
+
196
+ ---
197
+
198
+ ## Exemplo C# completo
199
+
200
+ ```csharp
201
+ // SEM `using OpenAI.Images;`. Ele nao e necessario aqui — o gerador chega injetado e nenhum
202
+ // tipo do SDK da OpenAI aparece neste arquivo — e deixa-lo torna `ImageGenerationOptions`
203
+ // AMBIGUO (CS0104) entre Microsoft.Extensions.AI e OpenAI.Images. Onde os dois convivem de
204
+ // verdade, como no adaptador do kit, o tipo vai QUALIFICADO.
205
+ using Microsoft.Extensions.AI;
206
+
207
+ // O pragma abre ACIMA da classe, e nao dentro do metodo: o parametro do construtor primario
208
+ // tambem nomeia IImageGenerator, e MEAI001 e ERRO por padrao — nao aviso. Pragma dentro do
209
+ // corpo deixa a assinatura de fora e o arquivo nao compila.
210
+ #pragma warning disable MEAI001 // IImageGenerator/ImageGenerationRequest sao experimentais: a superficie pode mudar entre menores.
211
+
212
+ /// <summary>
213
+ /// Adaptador de PROVIDER. Note o que ele NAO e: um servico publico que um handler
214
+ /// possa chamar. Quem produz bytes vive atras do enfileiramento descrito em
215
+ /// ai-agents/media-pipeline.md, e no kit esse tipo e `internal` de proposito.
216
+ /// </summary>
217
+ /// <remarks>
218
+ /// O IImageGenerator chega INJETADO, e nao construido aqui. As duas formas de obte-lo
219
+ /// sao legitimas e a escolha e do seu pin (ver a ressalva da secao "A API"):
220
+ /// - com Microsoft.Extensions.AI.OpenAI no pin: imageClient.AsIImageGenerator()
221
+ /// - sem ele: um IImageGenerator escrito a mao sobre o ImageClient, como em
222
+ /// templates/dotnet/ai-kit/src/Morph.AiKit/Media/Providers/OpenAIImageProvider.cs
223
+ /// Injetar em vez de construir e o que faz ESTE exemplo compilar nos dois casos.
224
+ /// </remarks>
225
+ internal sealed class OpenAiImageAdapter(IImageGenerator generator)
226
+ {
227
+ // ReadOnlyMemory<byte> dos dois lados porque e o tipo REAL de DataContent.Data.
228
+ // Declarar BinaryData aqui nao converte (CS0029) — e o compilador que decide isso.
229
+ public async Task<ReadOnlyMemory<byte>> ProduceAsync(
230
+ string prompt,
231
+ IReadOnlyList<ReadOnlyMemory<byte>> references,
232
+ CancellationToken ct)
233
+ {
234
+ var request = new ImageGenerationRequest { Prompt = prompt };
235
+ if (references.Count > 0)
236
+ {
237
+ // OriginalImages e o gancho de EDICAO: preserva o produto real em vez de recria-lo.
238
+ request.OriginalImages = [.. references.Select(r => new DataContent(r, "image/png"))];
239
+ }
240
+
241
+ var options = new ImageGenerationOptions
242
+ {
243
+ MediaType = "image/png",
244
+ Count = 1,
245
+ // Nao ha propriedade tipada para quality/background/input_fidelity na 10.9.0.
246
+ AdditionalProperties = new() { ["quality"] = "low" },
247
+ };
248
+
249
+ var response = await generator.GenerateAsync(request, options, ct);
250
+
251
+ return response.Contents.OfType<DataContent>().First().Data;
252
+ }
253
+ }
254
+
255
+ #pragma warning restore MEAI001
256
+ ```
257
+
258
+ **Escada de qualidade, e ela é obrigatória:** gere N candidatas em `low`, escolha com humano, e só
259
+ então regenere a vencedora em `high`. A conta de gerar tudo em `high` está em §Custo por chamada.
260
+
261
+ ---
262
+
263
+ ## Parâmetros
264
+
265
+ > Superfície de `ImageGenerationOptions` medida contra `Microsoft.Extensions.AI.Abstractions`
266
+ > 10.9.0; parâmetros de wire medidos contra a Images API da OpenAI.
267
+
268
+ | Parâmetro | Onde vive | Nota |
269
+ |---|---|---|
270
+ | `ModelId` | tipado | Vem do alias, nunca do handler |
271
+ | `Count` | tipado | N candidatas numa chamada; cobra por imagem |
272
+ | `ImageSize` | tipado (`System.Drawing.Size`) | `gpt-image-2` aceita múltiplos de 16 px até 3840 px de lado |
273
+ | `MediaType` | tipado | `image/png`, `image/jpeg`, `image/webp` |
274
+ | `ResponseFormat` | tipado | Prefira bytes. URL de provedor expira — ver §Deprecações e `media-pipeline.md` |
275
+ | `StreamingCount` | tipado | Imagens parciais (0-3) para feedback de UI interna |
276
+ | `quality` | `AdditionalProperties` | `low`/`medium`/`high`/`auto`. **Não é tipado na 10.9.0** |
277
+ | `background` | `AdditionalProperties` | `transparent`/`opaque`/`auto`; exige PNG ou WebP |
278
+ | `moderation` | `AdditionalProperties` | `auto`/`low`. Bloqueio é `rejected_by_policy`, não erro técnico |
279
+ | `output_compression` | `AdditionalProperties` | 0-100, só JPEG/WebP |
280
+ | `mask` | só Images API direto | PNG com alfa, mesmas dimensões da primeira referência |
281
+
282
+ Nada em `AdditionalProperties` é validado em compilação. Um erro de digitação ali é um parâmetro que
283
+ o provedor ignora em silêncio — cubra com teste de contrato o mapa nome→valor que o seu adaptador
284
+ monta.
285
+
286
+ ---
287
+
288
+ ## Custo por chamada
289
+
290
+ > **Toda a aritmética de dinheiro deste standard mora nesta seção, e em lugar nenhum mais.**
291
+ > Re-verificar preço é reabrir esta seção e §Deprecações — não reler o standard inteiro.
292
+
293
+ Preço de **lista pública**, em USD, sem desconto de contrato. Consultadas em **2026-09-07**:
294
+ `https://developers.openai.com/api/docs/pricing` e `https://ai.google.dev/gemini-api/docs/pricing`.
295
+
296
+ | Item | Preço | Origem |
297
+ |---|---|---|
298
+ | `gpt-image-2` — token de imagem de saída | $30,00 / 1M | OpenAI pricing (lista) |
299
+ | `gpt-image-2` — 1024², low / medium / high | ≈ $0,006 / $0,053 / $0,211 | **Estimativa de terceiro**, derivada da calculadora (`https://wavespeed.ai/blog/posts/gpt-image-2-pricing-2026/`). **Não é preço de lista** — a OpenAI publica por token |
300
+ | `gemini-3.1-flash-lite-image` | $0,0336 (Batch = Standard) | Gemini pricing |
301
+ | `gemini-3.1-flash-image` — 1K | $0,067 (Batch $0,034) | Gemini pricing |
302
+ | `gemini-3-pro-image` — 1K/2K | $0,134 (Batch $0,067) | Gemini pricing |
303
+ | Batch API (OpenAI e Google) | −50 % | páginas de pricing acima |
304
+
305
+ **A ressalva da segunda linha é parte do standard, não rodapé.** O preço por imagem do `gpt-image-2`
306
+ não tem fonte primária: a única tarifa oficial é por token. Um número derivado por terceiro serve
307
+ para dimensionar teto de orçamento, nunca para faturar cliente.
308
+
309
+ Três consequências de desenho, não de opinião:
310
+
311
+ 1. **Escada de qualidade.** A diferença entre `low` e `high` na estimativa acima é de mais de 30×.
312
+ Candidatas em `low`; `high` só na aprovada.
313
+ 2. **Batch para catálogo.** Metade do preço em lote é a maior alavanca isolada disponível. A decisão
314
+ Batch × Flex × síncrono já está escrita: `ai-agents/batching.md` e `ai-agents/service-tier-flex.md`.
315
+ 3. **Custo estimado gravado ANTES da chamada**, e teto por tenant/dia em unidades (imagens ×
316
+ qualidade). O mecanismo está em `ai-agents/media-pipeline.md`; a tarifa está aqui.
317
+
318
+ Token de imagem de **entrada** (edição com referência) também é cobrado, e `input_fidelity: high`
319
+ nos modelos legados aumenta a fatura. Edição não é mais barata que geração por definição.
320
+
321
+ ---
322
+
323
+ ## Deprecações
324
+
325
+ > **Toda data de desligamento deste standard mora nesta seção, e em lugar nenhum mais.**
326
+
327
+ Fontes, consultadas em **2026-09-07**: `https://developers.openai.com/api/docs/deprecations` e
328
+ `https://ai.google.dev/gemini-api/docs/imagen` (mais o changelog em
329
+ `https://ai.google.dev/gemini-api/docs/changelog`).
330
+
331
+ | Alias | Situação | Data |
332
+ |---|---|---|
333
+ | `gpt-image-1`, `gpt-image-1-mini`, `gpt-image-1.5`, `chatgpt-image-latest` | **desligam** (anunciado 2026-06-02) | 2026-12-01 |
334
+ | `dall-e-2`, `dall-e-3` | **desligados** | 2026-05-12 |
335
+ | `imagen-4.0-generate-001` e irmãos | **desligado** (anunciado 2026-06-15) | 2026-08-17 |
336
+ | `gemini-2.5-flash-image` | legado, migrar — sem data anunciada | — |
337
+ | `sora-2`, `sora-2-pro` (vídeo) | **desligam, sem substituto** | 2026-09-24 — ver `ai-agents/media-video.md` |
338
+
339
+ **Próximo desligamento conhecido: 2026-09-24.** Se esta data já passou quando você está lendo, este
340
+ standard não está apenas velho — ele está **errado**, e a §Como re-verificar diz em qual página
341
+ conferir. Uma data no passado nesta linha é falsificação em segundos, sem pesquisa.
342
+
343
+ O alias `dall-e` continua na busca do `STANDARDS.json` de propósito: quem procurar pelo modelo morto
344
+ tem de cair **aqui**, no lugar que diz que ele morreu.
345
+
346
+ ---
347
+
348
+ ## Anti-patterns
349
+
350
+ | Anti-pattern | Por quê é errado | Jeito certo |
351
+ |---|---|---|
352
+ | Gerar imagem quando asset estático resolve | Custo e latência sem ganho | Sirva de CDN |
353
+ | **Gerar dentro do turno de conversa** | Latência de até 2 min, custo por mensagem, zero revisão | Enfileire e confirme (`media-pipeline.md`) |
354
+ | **Usar alias em lista de desligamento** | Dinheiro gasto num endpoint com data de morte | Confira §Deprecações antes de pinar |
355
+ | **Gravar a URL do provedor em vez dos bytes** | URL de provedor expira; o link quebra depois | Baixe, grave no blob próprio, guarde caminho + sha256 |
356
+ | **Gerar do zero quando o produto real existe** | Inventa material, medida ou cor que o produto não tem — claim visual falso | Edição com `OriginalImages` / `/v1/images/edits` |
357
+ | Não moderar o prompt antes de enviar | Erro 400 sem log útil e conteúdo impróprio | Valide antes; ver `ai-agents/middleware-patterns.md` |
358
+ | Criar `AIAgent` para geração de imagem | `IImageGenerator` não é `IChatClient` | Serviço enfileirado, não agente |
359
+ | Suprimir `MEAI001` sem comentário | Silencia o aviso e esconde o risco de breaking change | `#pragma` com o motivo escrito na linha |
360
+
361
+ ---
362
+
363
+ ## Checklist (verifiable by morph-eval)
364
+
365
+ - [ ] O alias escolhido **não** está na tabela de §Deprecações
366
+ - [ ] A chamada passa por `IImageGenerator` (ou adaptador próprio), sem acoplar o handler ao SDK
367
+ - [ ] `MEAI001` suprimido explicitamente, com comentário do risco na mesma linha
368
+ - [ ] Edição com referência usa `OriginalImages` / `/v1/images/edits` quando o produto real existe
369
+ - [ ] Prompt montado por template versionado, com a estrutura fixa e a "preserve list" repetida
370
+ - [ ] `quality` mínimo por finalidade — candidatas em `low`, `high` só na aprovada
371
+ - [ ] Custo estimado gravado **antes** da chamada, com a tarifa de §Custo por chamada
372
+ - [ ] Bytes gravados em blob próprio; nenhuma URL de provedor persistida como se fosse permanente
373
+ - [ ] Nenhuma geração dentro de um turno de conversa — o handler devolve id de job
374
+ - [ ] Nenhum teste toca API paga
375
+
376
+ ---
377
+
378
+ ## Como re-verificar este standard
379
+
380
+ Cinco páginas, cinco perguntas. Cabe numa sessão; é o custo que torna o corte de 90 dias cumprível
381
+ em vez de desativado por allowlist.
382
+
383
+ | Página | O que conferir |
384
+ |---|---|
385
+ | `https://developers.openai.com/api/docs/deprecations` | A tabela de §Deprecações inteira, e a linha "próximo desligamento conhecido" |
386
+ | `https://developers.openai.com/api/docs/pricing` | O preço por token de saída de imagem, e se apareceu preço por imagem oficial (hoje não há) |
387
+ | `https://ai.google.dev/gemini-api/docs/pricing` | As três linhas Gemini de §Custo por chamada |
388
+ | `https://ai.google.dev/gemini-api/docs/image-generation` | Limites de referência da §Referências de produto |
389
+ | `https://learn.microsoft.com/en-us/dotnet/api/microsoft.extensions.ai.imagegenerationoptions` + `https://www.nuget.org/packages/Microsoft.Extensions.AI` | Se `quality`/`background` ganharam propriedade tipada, e se `MEAI001` saiu do experimental |
390
+
391
+ **E o exemplo, que é uma afirmação verificável, se re-verifica compilando — não lendo:**
392
+
393
+ ```bash
394
+ node scripts/extract-doc-csharp.mjs \
395
+ framework/standards/ai-agents/modalities-image-gen.md \
396
+ "## Exemplo C# completo" /tmp/probe/Exemplo.cs
397
+ cd /tmp/probe && dotnet build # csproj com o pin + TreatWarningsAsErrors
398
+ ```
399
+
400
+ O `TreatWarningsAsErrors` é obrigatório na sonda: sem ele `MEAI001` vira aviso e o build fica verde
401
+ sobre um exemplo que o consumidor **não** consegue compilar. Este bloco foi medido nos dois
402
+ cenários do pin — com e sem `Microsoft.Extensions.AI.OpenAI` — e sai `0 Aviso(s), 0 Erro(s)` nos
403
+ dois. Antes disso ele carregava três erros independentes, nenhum ligado ao pacote-ponte.
404
+
405
+ Ao terminar, atualize `Last-verified` **e** o `ai-pin` citado no header — re-datar sem re-verificar é
406
+ o defeito que `scripts/check-freshness.js` existe para impedir.
407
+
408
+ ---
409
+
410
+ ## References
411
+
412
+ - `ai-agents/media-pipeline.md` — o job, a revisão humana, a marcação e a regra dura
413
+ - `ai-agents/media-video.md` — vídeo em runtime, e o desligamento da Sora
414
+ - `frontend/design-system/ai-image-generation.md` — autoria de asset de LP via MCP: prompt craft de
415
+ marca, `assets.md`, `next/image`. Consumidor diferente, tempo diferente
416
+ - `ai-agents/batching.md` · `ai-agents/service-tier-flex.md` — a decisão Batch × Flex × síncrono
417
+ - `ai-agents/providers/model-registry.md` — o alias por provedor
418
+ - `ai-agents/setup.md` — pacotes e DI
419
+
420
+ ---
421
+
422
+ *MORPH-SPEC by Polymorphism Tech — ai-agents/modalities-image-gen.md v2.0*