@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
@@ -5,7 +5,7 @@
5
5
  > **Keywords:** observability, telemetry, opentelemetry, logging, tracing, log investigation, troubleshooting, aspire dashboard, span, correlation id
6
6
  > **Read by Claude in:** implement (wiring telemetry into an agent) and troubleshoot (investigating a production issue)
7
7
 
8
- **Verified against:** MAF 1.0 GA. Last-verified: 2026-07-22.
8
+ **Verified against:** Microsoft.Agents.AI 1.20.0 + Microsoft.Extensions.AI 10.9.0 (ai-pin 2026-09-08); `provado por templates/dotnet/ai-kit/src/Morph.AiKit/Observability/MorphOpenTelemetryExtensions.cs` — o guard de span duplicado, a regra de "um nível, uma instrumentação" e o default `EnableSensitiveData = false` são exatamente o que o kit compila, com os spans contados em `tests/Morph.AiKit.Tests/TelemetryTests.cs`. Nomes de símbolo, de span, de métrica e das duas `ActivitySource` foram **medidos por reflexão e por leitura dos literais das assemblies do pin** em 2026-09-08, e em 2026-09-09 **todos os treze nomes `gen_ai.*` desta página** foram remedidos, um a um, por **teste de exclusividade**: os quatro `SetTag` da seção *Enrichment* e os nove das seções de span, métrica e atributo de agente. **Os treze existem** — depois de uma correção: `gen_ai.response.finish_reason`, no **singular**, não existia, só aparecia como cabeça de `finish_reason`**s**, e sobreviveu a duas varreduras porque as duas usaram `includes` — e **`includes` de um prefixo não prova o literal autônomo**. Os treze estão tabelados, em **duas** tabelas com propósitos diferentes: a de *Enrichment* registra os **4** `SetTag` daquele bloco (mais os **cinco** nomes rejeitados: o `finish_reason` singular, `PromptTokens`, `CompletionTokens`, `prompt_tokens` e `completion_tokens`), e a de distribuição, na seção *Nomes de span, métricas e atributos — medidos*, registra os **13** por assembly. A conferência é reproduzível por `node scripts/api-probe/probe.mjs tags` sobre este arquivo. A **instabilidade da convenção** — o split do semconv **v1.42.0 (2026-06-12)**, que depreciou e moveu todo `gen_ai.*` para `open-telemetry/semantic-conventions-genai`, onde nada GenAI está `Stable`, contra a v1.37 que o `OpenTelemetryChatClient` declara implementar — é **verificação documental**, apurada em 2026-09-08. Last-verified: 2026-09-08.
9
9
 
10
10
  ---
11
11
 
@@ -17,28 +17,45 @@ Um agente MAF em produção não é uma função — é uma cadeia (LLM call →
17
17
 
18
18
  ## Setup — OpenTelemetry
19
19
 
20
+ ### Duas correções medidas contra a versão anterior deste standard
21
+
22
+ | O que este standard dizia | O que o pin diz (medido em 2026-09-08) |
23
+ |---|---|
24
+ | `AgentOpenTelemetryConsts.DefaultSourceName` e `agent.WithOpenTelemetry()` | **Nenhum dos dois existe** em `Microsoft.Agents.AI` 1.20.0. A API é `builder.UseOpenTelemetry(sourceName, configure)` sobre `AIAgentBuilder` / `ChatClientBuilder` |
25
+ | `EnableSensitiveTelemetryData` | O símbolo é **`EnableSensitiveData`**, e existe **nos dois** tipos: `OpenTelemetryAgent.EnableSensitiveData` e `OpenTelemetryChatClient.EnableSensitiveData`. Não são dois nomes diferentes: é o **mesmo nome em dois níveis** |
26
+ | *"não use `Experimental.Microsoft.Extensions.AI.*` — é do 9.x"* | São **duas fontes vivas e necessárias**: `Experimental.Microsoft.Agents.AI` (do agente) e `Experimental.Microsoft.Extensions.AI` (do chat e das tools). Quem só registra a primeira perde os spans `chat` e `execute_tool` |
27
+
28
+ Os dois nomes de `ActivitySource` foram lidos como literais nas assemblies `Microsoft.Agents.AI.dll` 1.20.0 e `Microsoft.Extensions.AI.dll` 10.9.0.
29
+
20
30
  ```csharp
21
31
  using OpenTelemetry;
22
32
  using OpenTelemetry.Trace;
23
33
  using OpenTelemetry.Metrics;
24
34
  using Microsoft.Agents.AI;
35
+ using Microsoft.Extensions.AI;
25
36
 
26
- // Habilitar em agents individuais
27
- agent.WithOpenTelemetry();
37
+ const string AgentSource = "Experimental.Microsoft.Agents.AI"; // span invoke_agent
38
+ const string ChatSource = "Experimental.Microsoft.Extensions.AI"; // spans chat e execute_tool
39
+
40
+ // Instrumentar o AGENTE (span externo). EnableSensitiveData default = false.
41
+ AIAgent instrumented = agent.AsBuilder()
42
+ .UseOpenTelemetry(sourceName: AgentSource, configure: o => o.EnableSensitiveData = false)
43
+ .Build();
28
44
 
29
45
  // Program.cs — setup completo
30
46
  builder.Services.AddOpenTelemetry()
31
47
  .WithTracing(tracing =>
32
48
  {
33
- tracing.AddSource(AgentOpenTelemetryConsts.DefaultSourceName); // MAF 1.0 GA source
34
- tracing.AddSource(builder.Environment.ApplicationName); // seus spans customizados (ver Enrichment)
49
+ tracing.AddSource(AgentSource); // sem isto: nenhum invoke_agent
50
+ tracing.AddSource(ChatSource); // sem isto: nenhum chat / execute_tool
51
+ tracing.AddSource(builder.Environment.ApplicationName); // seus spans customizados (ver Enrichment)
35
52
  tracing.AddAspNetCoreInstrumentation();
36
53
  tracing.AddHttpClientInstrumentation();
37
54
  tracing.AddOtlpExporter();
38
55
  })
39
56
  .WithMetrics(metrics =>
40
57
  {
41
- metrics.AddMeter(AgentOpenTelemetryConsts.DefaultSourceName);
58
+ metrics.AddMeter(ChatSource); // as métricas gen_ai.client.* saem daqui
42
59
  metrics.AddAspNetCoreInstrumentation();
43
60
  metrics.AddHttpClientInstrumentation();
44
61
  metrics.AddRuntimeInstrumentation();
@@ -52,9 +69,99 @@ builder.Logging.AddOpenTelemetry(logging =>
52
69
  });
53
70
  ```
54
71
 
55
- > **Source name:** sempre `AgentOpenTelemetryConsts.DefaultSourceName` de `Microsoft.Agents.AI`.
56
- > **NÃO usar** o source string `"Experimental.[pacote-antigo].*"` — pertence à família `Microsoft.Extensions.AI` 9.x, incompatível com MAF 1.0 GA.
57
- > **Produção:** desabilite dados sensíveis — `EnableSensitiveTelemetryData = false` no agent — para não vazar prompt/response completos no backend de export.
72
+ > **Produção:** `EnableSensitiveData = false` (é o default nos dois níveis) para não vazar prompt/response completos no backend de export.
73
+
74
+ ### A regra de duplicação — um NÍVEL, uma instrumentação
75
+
76
+ A mudança de **1.6.1** (2026-05-14) foi o `OpenTelemetryAgent` passar a **auto-encapsular** o chat client com um `OpenTelemetryChatClient` no pipeline que o `ChatClientAgent` monta sozinho. Daí saiu a regra folclórica *"instrumente o agente **ou** o chat client, nunca os dois"* — que é **imprecisa**, e a diferença muda o que se escreve.
77
+
78
+ **O que foi medido no pin** (`Morph.AiKit.Tests/TelemetryTests.cs`, contra `Microsoft.Agents.AI` 1.20.0):
79
+
80
+ - Uma invocação instrumentada produz **`invoke_agent` (raiz) + `chat` (filho)**. Instrumentar os **dois níveis** é o caminho normal, e **não** duplica nada — o teste `AnInstrumentedAgentEmitsOneInvokeAgentSpanAndOneChatSpan` pina isso.
81
+ - O que duplica é **duas camadas no MESMO nível**: dois `OpenTelemetryChatClient` dão dois `chat`; dois `OpenTelemetryAgent` dão dois `invoke_agent` (`ForcingInstrumentChatClientProducesTheDuplicateChatSpan`).
82
+ - O guard do MAF **só alcança o pipeline que o `ChatClientAgent` monta sozinho**. Quem monta o próprio pipeline (`ChatClientAgentOptions.UseProvidedChatClientAsIs = true`, necessário para posicionar middleware de custo ou ajustar tool calling) **perde** esse slot: medido, agente instrumentado + pipeline próprio sem instrumentação de chat = **zero** spans de chat.
83
+
84
+ **A regra correta, então, é em duas linhas:**
85
+
86
+ 1. **Instrumente cada nível no máximo uma vez.** O predicado é respondível, não um palpite: `inner.GetService(typeof(OpenTelemetryChatClient))` / `typeof(OpenTelemetryAgent)` atravessa a cadeia de delegates.
87
+ 2. **Com pipeline próprio, a instrumentação de chat é obrigatória** — não é um extra opcional, é a única coisa que produz o span `chat`.
88
+
89
+ ```csharp
90
+ // O guard, na forma que o ai-kit compila: nulo = instrumenta só o que ainda não está.
91
+ builder.Use(inner => inner.GetService(typeof(OpenTelemetryChatClient)) is null
92
+ ? new OpenTelemetryChatClient(inner, logger: null, sourceName: ChatSource) { EnableSensitiveData = false }
93
+ : inner);
94
+ ```
95
+
96
+ **Onde o span de chat fica no pipeline:** **abaixo** do `FunctionInvokingChatClient`. É assim que o span `chat` fecha antes das tools e o `invoke_agent` fica sendo a raiz. Ver a ordem completa do pipeline em `ai-agents-middleware-patterns`.
97
+
98
+ ### Nomes de span, métricas e atributos — medidos
99
+
100
+ | O que | Nome | Onde foi medido |
101
+ |---|---|---|
102
+ | Span do agente | `invoke_agent` | literal em `Microsoft.Agents.AI.dll` 1.20.0 |
103
+ | Span do modelo | operação + modelo (`gen_ai.operation.name` + `gen_ai.request.model`) | `Microsoft.Extensions.AI.dll` 10.9.0 |
104
+ | Span de tool | `execute_tool` | `Microsoft.Extensions.AI.dll` 10.9.0 |
105
+ | Métrica de duração | `gen_ai.client.operation.duration` | idem |
106
+ | Métrica de tokens | `gen_ai.client.token.usage` | idem |
107
+ | Métricas extras | `gen_ai.client.operation.exception`, `gen_ai.client.operation.time_per_output_chunk` | idem |
108
+ | Atributos do agente | `gen_ai.agent.id`, `gen_ai.agent.name`, `gen_ai.agent.description`, `gen_ai.provider.name` | `Microsoft.Agents.AI.dll` 1.20.0 |
109
+
110
+ A coluna "onde foi medido" nomeia **uma** assembly onde o literal ocorre, e **não** afirma
111
+ exclusividade. A distribuição completa, medida por exclusividade sobre **todas** as assemblies
112
+ restauradas do pin (`probe.mjs tags`, 2026-09-09) — repare que ela **não se limita às duas** que esta
113
+ página nomeia:
114
+
115
+ | Nome | Assemblies onde o literal ocorre |
116
+ |---|---|
117
+ | `invoke_agent` | `Microsoft.Agents.AI` **e** `Microsoft.Extensions.AI` |
118
+ | `execute_tool` | `Microsoft.Extensions.AI` **e** `ModelContextProtocol.Core` |
119
+ | `gen_ai.agent.id`, `gen_ai.agent.name`, `gen_ai.agent.description` | **só** `Microsoft.Agents.AI` |
120
+ | `gen_ai.provider.name` | `Microsoft.Agents.AI` **e** `Microsoft.Extensions.AI` |
121
+ | `gen_ai.operation.name` | `Microsoft.Agents.AI`, `Microsoft.Extensions.AI`, `ModelContextProtocol.Core` **e** `OpenAI` |
122
+ | `gen_ai.request.model`, `gen_ai.usage.input_tokens`, `gen_ai.usage.output_tokens`, `gen_ai.response.finish_reasons`, `gen_ai.client.operation.duration`, `gen_ai.client.token.usage` | `Microsoft.Extensions.AI` **e** `OpenAI` |
123
+ | `gen_ai.client.operation.exception`, `gen_ai.client.operation.time_per_output_chunk` | **só** `Microsoft.Extensions.AI` |
124
+
125
+ **Por que isto importa para quem instrumenta:** o mesmo nome emitido por camadas diferentes é o que
126
+ produz span duplicado — e é a razão de este standard começar pelo guard de "um nível, uma
127
+ instrumentação". `OpenAI` e `ModelContextProtocol.Core` estão sob o **mesmo pin** e carregam parte
128
+ destes nomes; se você registrar a fonte deles junto com a do agente sem o guard, o atributo chega
129
+ duas vezes com procedências diferentes.
130
+
131
+ > **Duas afirmações que NÃO se confirmaram, e por isso não estão acima.** `agent_framework.function.invocation.duration` e a variável de ambiente `OTEL_SEMCONV_STABILITY_OPT_IN=gen_ai_latest_experimental` **não aparecem** em nenhuma das quatro assemblies do pin (`Microsoft.Agents.AI`, `.Abstractions`, `Microsoft.Extensions.AI`, `.Abstractions`), varridas por literal em 2026-09-08. A duração de invocação de função pode existir noutro pacote, e a variável é do SDK do OpenTelemetry, não destes pacotes — em nenhum dos dois casos este standard as prescreve sem fonte.
132
+
133
+ ### Estabilidade da convenção GenAI — a ressalva que muda como ler a tabela acima
134
+
135
+ Os nomes acima são **medidos nas assemblies do pin**, e continuam corretos. O que não é estável é a
136
+ **convenção** que eles implementam, e um standard que manda instrumentar sem dizer isso está mandando
137
+ pintar alvo num muro que se move.
138
+
139
+ Os fatos, apurados em 2026-09-08:
140
+
141
+ - As **GenAI semantic conventions saíram do repositório principal** do OpenTelemetry. A versão
142
+ **1.42.0 do semconv (2026-06-12)** depreciou e moveu todo o namespace `gen_ai.*`; a **1.43.0
143
+ (2026-07-03)** não traz nenhum.
144
+ - O conteúdo passou a viver em `open-telemetry/semantic-conventions-genai`, e ali **nenhum** span,
145
+ evento, métrica ou atributo GenAI está marcado `Stable` — todos estão em `Development`. Os únicos
146
+ estáveis no conjunto são `error.type`, `server.address` e `server.port`, que são **atributos
147
+ comuns**, não GenAI.
148
+ - Enquanto isso, o `OpenTelemetryChatClient` do `Microsoft.Extensions.AI` declara implementar a
149
+ **v1.37** — ou seja, a versão implementada está **atrás** do split.
150
+
151
+ **O que isso implica na prática, e é o que se leva daqui:**
152
+
153
+ | Implicação | O que fazer |
154
+ |---|---|
155
+ | Nome de atributo `gen_ai.*` pode mudar entre versões do pacote | Não construa alerta cujo único identificador seja um nome `gen_ai.*` sem um plano de renomeação |
156
+ | A versão implementada pelo pacote **não** é a última da convenção | Ao subir o pin, confira a tabela de nomes acima em vez de assumir continuidade |
157
+ | Painel montado sobre o namespace instável envelhece com o pacote | Vale a pena manter uma camada própria de nomes (`morph.*`) para o que o time consulta todo dia |
158
+
159
+ Isto **não** é motivo para não instrumentar. É motivo para instrumentar sabendo que os nomes são de
160
+ uma convenção em desenvolvimento, e para não tratar uma renomeação futura como incidente.
161
+
162
+ ### Limitação conhecida, em aberto
163
+
164
+ Issue **3637** do `microsoft/agent-framework`: o `UseOpenTelemetry()` do .NET **não emite `ActivityEvent`s** conforme a spec de eventos GenAI — o conteúdo de mensagem viaja como atributo, não como evento. Estado em 2026-09-08: **aberta**. Consequência prática: um backend que monta a conversa a partir de *events* GenAI mostra spans sem mensagens. Não é bug do seu wiring.
58
165
 
59
166
  ### Aspire Dashboard (dev/local)
60
167
 
@@ -81,12 +188,54 @@ Sem um `correlation_id` propagado manualmente através de chamadas assíncronas/
81
188
 
82
189
  ```csharp
83
190
  activity?.SetTag("gen_ai.request.model", modelAlias); // alias do Model Registry, nunca o nome hardcoded
84
- activity?.SetTag("gen_ai.usage.prompt_tokens", usage.PromptTokens);
85
- activity?.SetTag("gen_ai.usage.completion_tokens", usage.CompletionTokens);
86
- activity?.SetTag("gen_ai.response.finish_reason", finishReason);
191
+ activity?.SetTag("gen_ai.usage.input_tokens", usage.InputTokenCount);
192
+ activity?.SetTag("gen_ai.usage.output_tokens", usage.OutputTokenCount);
193
+ activity?.SetTag("gen_ai.response.finish_reasons", finishReasons); // PLURAL — o singular não existe no pin
87
194
  ```
88
195
 
89
- Nomeação `gen_ai.*` segue a convenção semântica OpenTelemetry para GenAI — mantém compatibilidade se o backend de observability tiver dashboards prontos para essa convenção.
196
+ > **Correção de 2026-09-09 (duas passadas), medida por reflexão e por literal nas assemblies do
197
+ > pin. As QUATRO linhas acima foram conferidas, uma a uma** — a primeira passada corrigiu duas e
198
+ > deixou uma errada no mesmo bloco, que é a razão de este callout listar todas em vez de só as que
199
+ > mudaram.
200
+ >
201
+ > | Tag / símbolo | Veredito | Como |
202
+ > |---|---|---|
203
+ > | `gen_ai.request.model` | **existe** | 2 ocorrências autônomas; **distribuição por assembly na tabela da seção _Nomes de span, métricas e atributos — medidos_** — não é exclusivo de uma |
204
+ > | `gen_ai.usage.input_tokens` | **existe** | 2 autônomas; distribuição na tabela citada acima |
205
+ > | `gen_ai.usage.output_tokens` | **existe** | 2 autônomas; distribuição na tabela citada acima |
206
+ > | `gen_ai.response.finish_reasons` (a linha acima, no **plural**) | **existe** | 2 autônomas; distribuição na tabela citada acima |
207
+ > | `gen_ai.response.finish_reason` (o **singular**, que estava aqui) | **NÃO existe** | as **mesmas** 2 ocorrências do plural, **nenhuma autônoma**: o singular é a cabeça de `finish_reason`**s** |
208
+ > | `usage.PromptTokens` / `CompletionTokens` | **NÃO existem** | 0 ocorrências autônomas em assembly restaurada nenhuma |
209
+ > | `gen_ai.usage.prompt_tokens` / `completion_tokens` | **NÃO existem** | 0 ocorrências autônomas em assembly restaurada nenhuma |
210
+ >
211
+ > O que existe no lugar dos dois últimos é `InputTokenCount` / `OutputTokenCount`, propriedades de
212
+ > `UsageDetails` — que vive na assembly **`Microsoft.Extensions.AI.Abstractions` 10.9.0** (que viaja dentro do pacote `Microsoft.Extensions.AI`, e não é id de pacote do pin), e não na assembly
213
+ > que carrega os literais. E **"a assembly que carrega os literais" não é uma só** — a distribuição
214
+ > completa, por nome, está na tabela da seção *Nomes de span, métricas e atributos — medidos*, e **esta linha não a
215
+ > repete**: uma segunda tabela dos mesmos nomes foi escrita aqui na rodada 5 e **contradizia** a
216
+ > primeira (dizia "só em `Microsoft.Extensions.AI`" para seis literais que também vivem em `OpenAI`),
217
+ > justamente por invocá-la como autoridade sem relê-la. Duas cópias do mesmo fato divergem; a
218
+ > segunda foi removida.
219
+ >
220
+ > Faz sentido: quem **emite** o span de chamada de modelo é `OpenTelemetryChatClient`
221
+ > (`Microsoft.Extensions.AI` 10.9.0); quem descreve o **agente** é a camada de agente. Os nomes
222
+ > velhos eram da convenção **anterior** à renomeação do semconv. Código copiado daqui não compilava,
223
+ > e a tag emitida não casaria com nenhum painel montado sobre a convenção atual.
224
+ >
225
+ > **O método importa tanto quanto o resultado:** `finish_reason` sobreviveu a duas varreduras porque
226
+ > as duas usaram `includes(literal)`, e **`includes` de um prefixo não prova o literal autônomo** —
227
+ > o singular casa dentro do plural. A conferência acima é por **exclusividade**: cada ocorrência é
228
+ > aceita só se o caractere anterior e o seguinte não forem `[A-Za-z0-9_.-]`. Literais de string .NET
229
+ > vivem no heap `#US` em **UTF-16**; a varredura cobre `#US` (UTF-16) e `#Strings` (ASCII).
230
+
231
+ Nomeação `gen_ai.*` segue a convenção semântica OpenTelemetry para GenAI — mantém compatibilidade se o backend de observability tiver dashboards prontos para essa convenção. Sobre a **instabilidade** dessa convenção, ver a ressalva na seção de Setup.
232
+
233
+ > **Tokens ficam aqui; dinheiro não.** A **tarifa** por alias (com data de verificação), o **cálculo**
234
+ > do custo (e as três armadilhas de fórmula: raciocínio cobrado como saída, entrada cacheada como
235
+ > subconjunto da entrada, taxa fixa de operação hospedada), o estado de um custo
236
+ > (`Computed`/`Waived`/`UsageMissing`, e por que `cost_usd` nunca é nulo) e o **teto de orçamento**
237
+ > têm **tratamento canônico** em **`ai-agents-cost-and-budget`**. Não duplicado aqui. A delegação é
238
+ > de mão dupla: aquele standard aponta de volta para esta seção quando o assunto é atributo de span.
90
239
 
91
240
  ### Logging estruturado com `ILogger` — sempre com scope
92
241
 
@@ -105,11 +254,57 @@ using (_logger.BeginScope(new Dictionary<string, object>
105
254
  ```
106
255
 
107
256
  - **Sempre** parâmetros nomeados no template (`{ToolName}`, não string interpolada) — permite querying estruturado no backend em vez de grep de texto livre.
108
- - **Nunca** logar o conteúdo completo do prompt/response em `Information` — isso é PII/dado sensível do cliente por padrão. Logar em `Debug` apenas, e só se `EnableSensitiveTelemetryData` estiver habilitado explicitamente para o ambiente.
257
+ - **Nunca** logar o conteúdo completo do prompt/response em `Information` — isso é PII/dado sensível do cliente por padrão. Logar em `Debug` apenas, e só se `EnableSensitiveData` estiver habilitado explicitamente para o ambiente.
109
258
  - **Nível de log por tipo de evento:** `Information` para início/fim de tool call e decisões do agent; `Warning` para retry/fallback de provider; `Error` apenas para falhas que geram resposta degradada ao usuário (não para toda exceção capturada e tratada).
110
259
 
111
260
  ---
112
261
 
262
+ ## Rastreabilidade do que foi ao provedor
263
+
264
+ A pergunta que a instrumentação existe para responder depois de um incidente é uma só: **dá para
265
+ reconstruir o que foi enviado ao provedor, e o que ele respondeu, neste turno?**
266
+
267
+ **A regra: prompt cru no harness; hash em produção.**
268
+
269
+ | Ambiente | O que se registra | Por quê |
270
+ |---|---|---|
271
+ | Dev e harness | O texto enviado, com **opt-in explícito** e sem dado pessoal | É onde se depura; o custo de vazamento é controlado |
272
+ | Produção | O **hash** do texto enviado (e, quando o prompt é composto de blocos, um hash por bloco) | Um prompt cru persistido em produção é um vazamento esperando indexação. O hash responde "foi o mesmo texto?" sem guardar o texto |
273
+
274
+ Isso é a mesma chave que `EnableSensitiveData = false` fora de dev já protege — e o hash é o que
275
+ sobra de útil depois de desligá-la.
276
+
277
+ ### A invariante que torna o hash confiável
278
+
279
+ Um hash só prova alguma coisa se o texto de que ele é hash **é** o texto que foi enviado. Isso deixa
280
+ de valer no instante em que existe um cache entre a montagem e o envio: a partir dali, telemetria e
281
+ requisição podem divergir, e a divergência é silenciosa.
282
+
283
+ Por isso a exigência é do lado de quem monta o prompt, não de quem o registra: **o texto enviado é
284
+ derivado dos blocos, sem cache**. É uma invariante deliberadamente cara, e a razão está escrita no
285
+ código de campo que a implementa — *"para a telemetria não poder mentir"*. O tratamento canônico
286
+ está em `ai-agents-conversational-agent-with-phases`, seção do compositor de turno.
287
+
288
+ **Duas asserções que fecham o ciclo**, e ambas são de teste, não de wiring:
289
+
290
+ - A lista de tools **ofertadas** saiu da lista real do turno, e não de uma constante paralela.
291
+ - **Turno cancelado não grava** — um registro de algo que não aconteceu é pior que a ausência dele.
292
+
293
+ A metade de harness deste assunto (o que o fake captura, e como assertar sobre isso) é de
294
+ `ai-agents-testing-ai`. O veredito ternário e o escape registrado, que são o que torna um guard
295
+ auditável pela mesma via, são de `ai-agents-guardrails`.
296
+
297
+ > **O que o Gate 3 procura.** Os nomes concretos — `ActivitySource`, spans, métricas e atributos
298
+ > requeridos — estão medidos na tabela **"Nomes de span, métricas e atributos — medidos"** acima, e
299
+ > **não** são repetidos aqui: uma segunda lista dos mesmos nomes é a segunda verdade nascendo. A
300
+ > régua de avaliação correspondente vive em
301
+ > `.morph/framework/evals/proof-rubrics/observabilidade-genai.md`, e ela pergunta a **propriedade**
302
+ > desta seção (dá para reconstruir o turno?), não a tecnologia — porque uma régua binária "tem span?"
303
+ > daria a mesma nota a quem tem só a mensagem da exceção e a quem tem hash por bloco de prompt com
304
+ > teste de fidelidade.
305
+
306
+ ---
307
+
113
308
  ## Investigação e análise — quando algo dá errado
114
309
 
115
310
  Workflow para diagnosticar um incidente relatado ("o agente X respondeu errado/lento/nada às HH:MM"):
@@ -134,12 +329,20 @@ Workflow para diagnosticar um incidente relatado ("o agente X respondeu errado/l
134
329
 
135
330
  ## Checklist (verifiable by morph-eval)
136
331
 
137
- - [ ] OpenTelemetry configurado com `AgentOpenTelemetryConsts.DefaultSourceName` (traces + metrics + logging)
138
- - [ ] `EnableSensitiveTelemetryData = false` fora de dev/staging
332
+ - [ ] `AddSource` das **duas** fontes: `Experimental.Microsoft.Agents.AI` e `Experimental.Microsoft.Extensions.AI`
333
+ - [ ] Nenhuma referência a `AgentOpenTelemetryConsts` ou `agent.WithOpenTelemetry()` (não existem no pin)
334
+ - [ ] `EnableSensitiveData = false` fora de dev/staging (é o default — confirme que ninguém ligou)
335
+ - [ ] Cada nível instrumentado **no máximo uma vez**; com `UseProvidedChatClientAsIs = true`, a instrumentação de chat está explicitamente presente
336
+ - [ ] Um teste conta os spans de uma invocação: exatamente um `invoke_agent` e um `chat`
139
337
  - [ ] Todo tool call relevante tem `correlation_id` propagado manualmente através de boundaries assíncronos (filas, background jobs)
140
338
  - [ ] Logging via `ILogger` com `BeginScope` estruturado, nunca string interpolada em templates de log
141
339
  - [ ] Nenhum log em `Information`/produção contém prompt/response completo
142
340
  - [ ] Alertas configurados para os thresholds da tabela "What to Monitor" relevantes ao projeto
341
+ - [ ] Nenhum alerta depende de um nome `gen_ai.*` como identificador único sem plano de renomeação (a convenção está em `Development`, não `Stable`)
342
+ - [ ] Em produção, o que foi ao provedor é reconstituível por **hash**; prompt cru só em dev/harness, com opt-in
343
+ - [ ] O texto enviado é derivado dos blocos **sem cache** — sem isso o hash não prova nada
344
+ - [ ] Há asserção de que a lista de tools ofertadas saiu da lista real do turno
345
+ - [ ] Turno cancelado **não** grava telemetria
143
346
 
144
347
  ---
145
348
 
@@ -147,10 +350,17 @@ Workflow para diagnosticar um incidente relatado ("o agente X respondeu errado/l
147
350
 
148
351
  - `ai-agents-production` — panorama de produção; esta seção era resumida lá, tratamento canônico agora aqui
149
352
  - `ai-agents-middleware-patterns` — middleware de telemetria no nível `IChatClient` (`TelemetryMiddleware`)
353
+ - `ai-agents-cost-and-budget` — tarifa, cálculo de custo e teto de orçamento (delegação recíproca: tokens ficam aqui, dinheiro fica lá)
354
+ - `ai-agents-conversational-agent-with-phases` — o compositor de turno e a invariante "derivado sem cache" que torna o hash confiável
355
+ - `ai-agents-testing-ai` — a metade de harness da rastreabilidade (captura do fake, prompt cru com opt-in)
356
+ - `ai-agents-guardrails` — veredito ternário e escape registrado, auditáveis pela mesma telemetria
357
+ - `.morph/framework/evals/proof-rubrics/observabilidade-genai.md` — a régua do Gate 3 para a propriedade desta seção
150
358
  - `infrastructure-docker-coolify-deploy` — Serilog/JSON console log para o pipeline de agregação em produção
359
+ - Reference implementation (compila e conta spans contra o pin): `templates/dotnet/ai-kit/src/Morph.AiKit/Observability/MorphOpenTelemetryExtensions.cs` + `tests/Morph.AiKit.Tests/TelemetryTests.cs`
151
360
  - [OpenTelemetry Semantic Conventions for GenAI](https://opentelemetry.io/docs/specs/semconv/gen-ai/)
152
361
  - [Agent Observability](https://learn.microsoft.com/agent-framework/user-guide/observability/)
362
+ - Issue aberta `microsoft/agent-framework#3637` — `ActivityEvent`s da spec GenAI não emitidos (estado em 2026-09-08: **aberta**)
153
363
 
154
364
  ---
155
365
 
156
- *MORPH-SPEC by Polymorphism Tech — ai-agents/observability-patterns.md v1.0 (2026-07-22)*
366
+ *MORPH-SPEC by Polymorphism Tech — ai-agents/observability-patterns.md v2.0 (2026-09-08)*