@polymorphism-tech/morph-spec 8.38.0 → 8.41.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 (242) hide show
  1. package/CLAUDE.md +20 -9
  2. package/README.md +2 -2
  3. package/bin/morph-spec.js +60 -43
  4. package/claude-plugin.json +1 -1
  5. package/docs/CHEATSHEET.md +1 -1
  6. package/docs/QUICKSTART.md +1 -1
  7. package/framework/CLAUDE.md +4 -3
  8. package/framework/MORPH.md +10 -9
  9. package/framework/agents.json +43 -26
  10. package/framework/docs/CLI.md +7 -5
  11. package/framework/evals/rubrics/code-quality.md +4 -4
  12. package/framework/evals/rubrics/condensed.md +2 -2
  13. package/framework/hooks/README.md +1 -1
  14. package/framework/hooks/claude-code/core/telemetry-log.js +39 -8
  15. package/framework/hooks/claude-code/core/worktree-create.js +22 -6
  16. package/framework/hooks/shared/git-paths.js +38 -5
  17. package/framework/mcp/registry.json +58 -66
  18. package/framework/rules/infrastructure-standards.md +0 -1
  19. package/framework/rules/morph-workflow.md +9 -4
  20. package/framework/skills/core/create-umbraco-lp/SKILL.md +1 -1
  21. package/framework/skills/core/migrate-lp-to-umbraco/SKILL.md +1 -1
  22. package/framework/skills/core/morph-apply/SKILL.md +59 -25
  23. package/framework/skills/core/morph-brainstorming/SKILL.md +1 -1
  24. package/framework/skills/core/morph-eval/SKILL.md +1 -1
  25. package/framework/skills/core/morph-hotfix/SKILL.md +2 -2
  26. package/framework/skills/core/morph-implement/SKILL.md +48 -24
  27. package/framework/skills/core/morph-media/SKILL.md +2 -2
  28. package/framework/skills/core/morph-plan/SKILL.md +10 -3
  29. package/framework/skills/core/morph-proposal/SKILL.md +1 -1
  30. package/framework/skills/core/morph-review/SKILL.md +1 -1
  31. package/framework/skills/core/morph-stack-scan/SKILL.md +1 -1
  32. package/framework/skills/core/morph-standards/SKILL.md +1 -1
  33. package/framework/skills/core/morph-uiux/SKILL.md +7 -6
  34. package/framework/standards/PROVENANCE.json +4 -4
  35. package/framework/standards/STANDARDS.json +9 -9
  36. package/framework/standards/ai-agents/context-providers.md +16 -26
  37. package/framework/standards/ai-agents/durable-workflows-hitl.md +15 -21
  38. package/framework/standards/ai-agents/modalities-image-gen.md +21 -25
  39. package/framework/standards/ai-agents/modalities-speech-to-text.md +4 -15
  40. package/framework/standards/ai-agents/modalities-text-to-speech.md +2 -11
  41. package/framework/standards/ai-agents/modalities-vision.md +1 -18
  42. package/framework/standards/ai-agents/prompt-sources.md +0 -4
  43. package/framework/standards/architecture/code-comments.md +52 -16
  44. package/framework/standards/backend/dotnet/testing.md +4 -2
  45. package/framework/standards/backend/integrations/neon-auth/neon-auth.md +63 -50
  46. package/framework/standards/frontend/design-system/ai-image-generation.md +42 -28
  47. package/framework/standards/frontend/design-system/ai-video-generation.md +24 -9
  48. package/framework/standards/frontend/nextjs/testing.md +4 -2
  49. package/framework/standards/integration/mcp/mcp-tools.md +64 -126
  50. package/framework/templates/code/dotnet/abstractions/result.cs +0 -2
  51. package/framework/templates/code/dotnet/ai-agents/AgentBootstrap.cs.template +26 -39
  52. package/framework/templates/code/dotnet/ai-agents/EmbeddingService.cs.template +28 -68
  53. package/framework/templates/code/dotnet/ai-agents/ModelRegistry.cs.template +99 -117
  54. package/framework/templates/code/dotnet/ai-agents/PromptRepository.cs.template +2 -44
  55. package/framework/templates/code/dotnet/ai-agents/ResilientToolMiddleware.cs.template +40 -61
  56. package/framework/templates/code/dotnet/ai-agents/VectorSearchTool.cs.template +54 -107
  57. package/framework/templates/code/dotnet/ai-agents/model-registry.json.template +53 -58
  58. package/framework/templates/code/dotnet/contracts/contracts-vsa.cs +192 -281
  59. package/framework/templates/code/dotnet/database/migration.cs +49 -83
  60. package/framework/templates/code/dotnet/database/vector-entity.cs +2 -46
  61. package/framework/templates/code/dotnet/extensions/result-extensions.cs +0 -2
  62. package/framework/templates/code/dotnet/feature/validator.cs.hbs +11 -15
  63. package/framework/templates/code/dotnet/jobs/agent.cs +3 -51
  64. package/framework/templates/code/dotnet/jobs/job.cs +2 -97
  65. package/framework/templates/code/dotnet/test.cs +2 -87
  66. package/framework/templates/code/typescript/contracts.ts +140 -167
  67. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Agents/AgentApi.cs +1 -48
  68. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Agents/AgentFactory.cs +3 -79
  69. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Agents/AgentFactoryOptions.cs +1 -70
  70. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Agents/AgentSpec.cs +1 -47
  71. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Agents/AgentSpecOptions.cs +2 -99
  72. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/AiKitAssemblyMarker.cs +0 -6
  73. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Conversation/ConversationStore.cs +3 -88
  74. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Conversation/IConversationStore.cs +1 -41
  75. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Conversation/InMemoryConversationStore.cs +0 -21
  76. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Evals/CountingChatClient.cs +1 -25
  77. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Evals/EvalAssertion.cs +2 -63
  78. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Evals/EvalCacheMissException.cs +0 -30
  79. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Evals/EvalCacheOptions.cs +1 -52
  80. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Evals/EvalCacheStamp.cs +3 -78
  81. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Evals/EvalFixture.cs +4 -109
  82. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Evals/EvalMode.cs +0 -22
  83. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Evals/EvalQualityEvaluators.cs +1 -36
  84. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Evals/EvalScenario.cs +2 -57
  85. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Evals/EvalSummary.cs +0 -75
  86. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Evals/OfflineChatClient.cs +2 -59
  87. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Evals/ShortPathResponseCache.cs +4 -111
  88. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/IMediaGenerator.cs +0 -34
  89. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/IMediaProvider.cs +1 -57
  90. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/MediaArtifact.cs +0 -19
  91. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/MediaDisclosure.cs +2 -74
  92. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/MediaGenerator.cs +2 -33
  93. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/MediaIdempotencyKey.cs +1 -43
  94. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/MediaJob.cs +1 -96
  95. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/MediaJobId.cs +0 -13
  96. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/MediaJobState.cs +0 -27
  97. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/MediaPricing.cs +0 -33
  98. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/MediaProvenance.cs +0 -31
  99. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/MediaRequest.cs +3 -75
  100. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/MediaResult.cs +0 -42
  101. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/MediaReview.cs +0 -39
  102. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/MediaSeams.cs +1 -55
  103. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/MediaStore.cs +3 -59
  104. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/MorphMedia.cs +0 -46
  105. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/Providers/GoogleImageProvider.cs +3 -28
  106. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/Providers/OpenAIImageProvider.cs +7 -61
  107. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/Providers/VeoVideoProvider.cs +2 -37
  108. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Middleware/IUsageCostSink.cs +1 -23
  109. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Middleware/UsageCostMiddleware.cs +2 -82
  110. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Middleware/UsageCostRecord.cs +1 -68
  111. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Observability/MorphOpenTelemetryExtensions.cs +1 -62
  112. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Observability/MorphTelemetryOptions.cs +2 -62
  113. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Providers/IProviderClientFactory.cs +1 -25
  114. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Providers/ModelAlias.cs +0 -124
  115. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Providers/ModelRegistry.cs +1 -73
  116. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Rag/DeltaIngest.cs +1 -66
  117. package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Rag/DeltaPlan.cs +0 -41
  118. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/AgentFactoryTests.cs +2 -112
  119. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/AgentSpecTests.cs +2 -43
  120. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/ConversationStoreTests.cs +5 -110
  121. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/DeltaIngestTests.cs +7 -103
  122. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Evals/EvalAssertionTests.cs +1 -42
  123. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Evals/EvalCacheMissTests.cs +1 -30
  124. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Evals/EvalCacheStampTests.cs +1 -19
  125. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Evals/EvalFailuresTests.cs +0 -48
  126. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Evals/EvalFixtureTests.cs +1 -29
  127. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Evals/EvalRefreshTests.cs +2 -38
  128. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Evals/EvalWorkspace.cs +1 -14
  129. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Evals/KitEvals.cs +4 -69
  130. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Evals/OfflineChatClientTests.cs +1 -10
  131. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Fakes/FakeChatClient.cs +1 -57
  132. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Fakes/FakeChatClientTests.cs +0 -26
  133. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Fakes/FakeClock.cs +1 -19
  134. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Fakes/FakeMediaProvider.cs +0 -32
  135. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Fakes/FakeProviderClientFactory.cs +0 -14
  136. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Fakes/FakeUsageCostSink.cs +0 -24
  137. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Fakes/InMemoryMediaStore.cs +0 -32
  138. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/MediaAccessibilityTests.cs +0 -37
  139. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/MediaAliasIsNotAnAgentTests.cs +0 -24
  140. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/MediaDisclosureTests.cs +0 -78
  141. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/MediaGeneratorTests.cs +0 -53
  142. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/MediaIdempotencyKeyTests.cs +0 -44
  143. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/MediaJobStateTests.cs +0 -44
  144. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/MediaReviewTests.cs +0 -19
  145. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/MediaStoreTests.cs +0 -24
  146. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/ModelRegistryTests.cs +6 -48
  147. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/SkeletonSmokeTests.cs +1 -13
  148. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/TelemetryTests.cs +2 -71
  149. package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/UsageCostMiddlewareTests.cs +5 -100
  150. package/framework/templates/frontend/nextjs/Dockerfile.nextjs.hbs +39 -43
  151. package/framework/templates/frontend/nextjs/env.mjs.hbs +29 -32
  152. package/framework/templates/frontend/nextjs/page.tsx.hbs +21 -22
  153. package/framework/templates/frontend/nextjs/use-feature.ts.hbs +42 -54
  154. package/framework/templates/integrations/asaas-client.cs +332 -387
  155. package/framework/templates/integrations/asaas-webhook.cs +290 -351
  156. package/framework/templates/integrations/neon-auth-config.cs +9 -105
  157. package/framework/templates/project/validate.js +97 -120
  158. package/package.json +2 -2
  159. package/src/commands/dashboard/dashboard.js +80 -53
  160. package/src/commands/mcp/mcp-setup.js +37 -9
  161. package/src/commands/project/doctor.js +12 -6
  162. package/src/commands/project/init.js +6 -3
  163. package/src/commands/project/install-plugin-cmd.js +1 -1
  164. package/src/commands/project/update.js +5 -0
  165. package/src/commands/project/worktree.js +60 -4
  166. package/src/commands/state/gate-check.js +5 -0
  167. package/src/commands/tasks/dag.js +27 -4
  168. package/src/commands/validation/verify.js +22 -38
  169. package/src/dashboard/app/App.jsx +80 -16
  170. package/src/dashboard/app/components/ActivityFeed.jsx +172 -0
  171. package/src/dashboard/app/components/CommandPalette.jsx +155 -0
  172. package/src/dashboard/app/components/DetailPanel.jsx +47 -11
  173. package/src/dashboard/app/components/EntityLink.jsx +55 -0
  174. package/src/dashboard/app/components/ErrorBoundary.jsx +54 -0
  175. package/src/dashboard/app/components/FlowGraph.jsx +19 -17
  176. package/src/dashboard/app/components/KnowledgeMarkdown.jsx +53 -0
  177. package/src/dashboard/app/components/Markdown.jsx +47 -0
  178. package/src/dashboard/app/components/PhaseRail.jsx +111 -0
  179. package/src/dashboard/app/components/SearchFilter.jsx +40 -22
  180. package/src/dashboard/app/components/Sidebar.jsx +146 -37
  181. package/src/dashboard/app/hooks/useMorphQuery.js +54 -0
  182. package/src/dashboard/app/hooks/usePref.js +38 -0
  183. package/src/dashboard/app/lib/format.js +69 -0
  184. package/src/dashboard/app/lib/phases.js +56 -0
  185. package/src/dashboard/app/lib/project.js +50 -0
  186. package/src/dashboard/app/pages/Activity.jsx +24 -0
  187. package/src/dashboard/app/pages/AgentMap.jsx +371 -370
  188. package/src/dashboard/app/pages/FeatureDetail.jsx +604 -0
  189. package/src/dashboard/app/pages/Features.jsx +400 -0
  190. package/src/dashboard/app/pages/Guide.jsx +146 -0
  191. package/src/dashboard/app/pages/HookInspector.jsx +357 -322
  192. package/src/dashboard/app/pages/PhasePipeline.jsx +277 -408
  193. package/src/dashboard/app/pages/Portfolio.jsx +156 -0
  194. package/src/dashboard/app/pages/Rubrics.jsx +101 -0
  195. package/src/dashboard/app/pages/RulesMap.jsx +300 -273
  196. package/src/dashboard/app/pages/SkillsLibrary.jsx +483 -366
  197. package/src/dashboard/app/pages/Standards.jsx +407 -332
  198. package/src/dashboard/app/styles/index.css +187 -47
  199. package/src/dashboard/index.html +14 -12
  200. package/src/dashboard/package.json +32 -24
  201. package/src/dashboard/scanner/activity-scanner.js +351 -0
  202. package/src/dashboard/scanner/agents-scanner.js +59 -1
  203. package/src/dashboard/scanner/docs-scanner.js +59 -0
  204. package/src/dashboard/scanner/feature-status.js +10 -0
  205. package/src/dashboard/scanner/features-scanner.js +360 -0
  206. package/src/dashboard/scanner/index.js +14 -7
  207. package/src/dashboard/scanner/phases-scanner.js +14 -15
  208. package/src/dashboard/scanner/portfolio.js +153 -0
  209. package/src/dashboard/scanner/project-api.js +195 -0
  210. package/src/dashboard/scanner/rules-scanner.js +42 -37
  211. package/src/dashboard/scanner/skills-scanner.js +105 -43
  212. package/src/dashboard/scanner/standards-scanner.js +2 -0
  213. package/src/dashboard/vite-plugin-morph-data.js +134 -17
  214. package/src/lib/detectors/claude-config-detector.js +2 -7
  215. package/src/lib/detectors/index.js +5 -1
  216. package/src/lib/evaluator-report.js +22 -0
  217. package/src/lib/generators/settings-generator.js +208 -209
  218. package/src/lib/installers/mcp-installer.js +724 -719
  219. package/src/lib/installers/memory-installer.js +1 -2
  220. package/src/lib/projects/registry.js +154 -0
  221. package/src/lib/risk-detector.js +13 -0
  222. package/src/lib/tasks/tasks-json-parser.js +21 -0
  223. package/src/lib/validators/code-budget/code-budget-validator.js +32 -4
  224. package/src/lib/worktree/env-allocator.js +9 -3
  225. package/src/scripts/install-plugin.js +1 -1
  226. package/src/scripts/setup-infra.js +2 -4
  227. package/src/utils/agents-installer.js +108 -13
  228. package/src/utils/banner.js +1 -1
  229. package/src/commands/index.js +0 -13
  230. package/src/commands/project/checkpoint.js +0 -209
  231. package/src/core/state/phase-state-machine.js +0 -197
  232. package/src/dashboard/app/hooks/useDetailPanel.js +0 -15
  233. package/src/dashboard/app/pages/LiveState.jsx +0 -206
  234. package/src/dashboard/scanner/squads-scanner.js +0 -13
  235. package/src/dashboard/scanner/state-scanner.js +0 -85
  236. package/src/lib/generators/index.js +0 -10
  237. package/src/lib/hooks/hook-executor.js +0 -167
  238. package/src/lib/validators/checkpoint-persistence.js +0 -39
  239. package/src/lib/validators/shared/emit-validator-dispatch.js +0 -14
  240. package/src/lib/validators/shared/index.js +0 -12
  241. package/src/lib/validators/shared/issue-counter.js +0 -14
  242. package/src/lib/validators/shared/result-formatter.js +0 -124
@@ -4,7 +4,7 @@ description: Guia a execução de cada tarefa de implementação com standard e
4
4
  version: core
5
5
  when-to-invoke: ao iniciar cada task de implementação listada em tasks.json
6
6
  user-invokable: false
7
- cliVersion: "8.38.0"
7
+ cliVersion: "8.41.0"
8
8
  ---
9
9
 
10
10
  # morph-implement
@@ -54,12 +54,14 @@ Ao iniciar cada task de `tasks.json` — antes de escrever qualquer código. Nor
54
54
 
55
55
  > **Relação com `morph-spec dag`:** a decisão do DAG (na `morph-apply` §2) governa o **paralelismo ENTRE tasks** — quantos sub-agents rodam ao mesmo tempo. Os gatilhos acima governam o **dispatch INDIVIDUAL desta task**. São ortogonais e coexistem: `DAG: sequencial` NÃO significa "tudo inline" — significa "uma task por vez, na ordem". Exemplo: cadeia única backend de 12 tasks (DAG: sequencial); T7 tem effort L → despache T7 sozinha para `morph-dotnet-senior` e aguarde o retorno antes de seguir; T8 (S, mesmo domínio) roda inline.
56
56
 
57
- **Se for despachar — use `subagent_type: "morph-{id}"` do agente identificado no passo 3.** Os subagents são gerados de `agents.json` na instalação (`.claude/agents/morph-{id}.md`) e a persona é o **system prompt** deles — não a cole no prompt. **Fallback:** se `morph-{id}` não estiver na sua lista de subagent types (stack não instalado), use `general-purpose` colando o campo `persona` no prompt e registre nas `notes` da task: `dispatch-fallback: general-purpose ({id} não registrado)`. Template do prompt (cláusulas do relatório em forma curta — racional completo em `MORPH.md` §6):
57
+ **Se for despachar — use `subagent_type: "morph-{id}"` do agente identificado no passo 3.** Os subagents são gerados de `agents.json` na instalação (`.claude/agents/morph-{id}.md`) e a persona é o **system prompt** deles — não a cole no prompt. **Fallback:** se `morph-{id}` não estiver na sua lista de subagent types (stack não instalado), use `general-purpose` colando o campo `persona` no prompt e registre nas `notes` da task: `dispatch-fallback: general-purpose ({id} não registrado)`. Template do prompt (cláusulas do relatório em forma curta — racional completo em `MORPH.md` §6). **Cole-o literal**: só os campos entre colchetes mudam; não parafraseie cláusula nem omita os parágrafos de leitura, ferramentas e comentário — foi assim que regras chegaram tortas ao sub-agent em campo:
58
58
  ```
59
59
  Implementar [ID]: [title da task]
60
60
 
61
61
  Spec: [description completa do tasks.json]
62
- Standard: [path do .md do standard identificado no passo 2]
62
+ Standards: [por standard: `id` + o digest do `standards --find` + as 3-8 regras
63
+ do .md que ESTA task aplica, coladas. O path vai junto só para consulta
64
+ pontual — o sub-agente não relê standards inteiros]
63
65
  Arquivos relevantes: [os `target` de task.reuse + o que o scout/grafo apontou
64
66
  — este campo não é decorativo: é por ele que o código já existente chega
65
67
  ao sub-agente, que trabalha em contexto fresco e não conhece o projeto.
@@ -74,9 +76,25 @@ Ao iniciar cada task de `tasks.json` — antes de escrever qualquer código. Nor
74
76
  a ausência de grafo nunca bloqueia. Se algo cobre o caso, reuse ou estenda;
75
77
  se criar mesmo assim, diga por que em uma linha no relatório.
76
78
 
77
- Leitura: não releia o que este prompt já traz. Em arquivo grande, `Grep`
78
- acha a linha e `Read` com `offset`/`limit` lê só o trecho; leituras que não
79
- dependem uma da outra vão no mesmo turno, em paralelo.
79
+ Leitura e turnos: cada turno custa ~10 s antes de a tool rodar, e o teto de
80
+ turnos corta sem aviso. Chamadas que não dependem uma da outra vão no MESMO
81
+ turno: leia de uma vez todos os arquivos que este prompt lista, dispare os
82
+ Grep juntos. Use Read/Grep/Glob — nunca `grep`, `sed -n`, `cat`, `find`,
83
+ `ls` via Bash. Não releia o que este prompt já traz. Em arquivo grande, `Grep`
84
+ acha a linha e `Read` com `offset`/`limit` lê só o trecho; log de build/teste
85
+ se lê pelo `Grep` do erro, não inteiro.
86
+
87
+ Ferramentas: antes de supor a API de uma biblioteca (MAF, EF Core, Next,
88
+ shadcn, SDK de provedor), consulte o MCP `context7` (`resolve-library-id` →
89
+ `query-docs`). Impacto e vizinhança de símbolo vêm do grafo
90
+ (`morph-spec graph`), não de varredura por grep. Tool `mcp__…` que não esteja
91
+ carregada se carrega com `ToolSearch` (`select:<nome>`); MCP ausente nunca
92
+ bloqueia — siga com o fallback.
93
+
94
+ Comentário: o padrão é nenhum. Nome, tipo e teste explicam o código; sem
95
+ `///`/JSDoc em membro de aplicação, cabeçalho, banner de seção ou história
96
+ da task. Só o porquê que o código não mostra, em uma linha
97
+ (`architecture-code-comments`).
80
98
 
81
99
  Contrato do relatório final:
82
100
  1. GRAVE `.morph/features/{feature}/3-implement/reports/[ID].md` ANTES de
@@ -84,25 +102,28 @@ Ao iniciar cada task de `tasks.json` — antes de escrever qualquer código. Nor
84
102
  cortesia best-effort e pode não chegar inteira). NÃO chame SendMessage.
85
103
  2. NÃO toque em tasks.json, feature.json, state.json nem no board de sessão
86
104
  — todo estado é gravado exclusivamente pelo orquestrador.
87
- 3. Verificação condicional ao isolamento: em batch paralelo SEM isolamento,
88
- NÃO rode build/test da suíte compartilhada — a verificação
89
- (`morph-spec verify`) é do orquestrador, pós-batch. Em batch COM
90
- `isolation: "worktree"`, rode build/test no seu worktree, commite na
91
- branch do worktree como último ato antes do relatório — nunca faça merge.
92
- Worktree não commitado NÃO é removido pelo hook e vira pendência do
93
- `doctor`; o commit é o que torna o seu trabalho integrável.
94
- Ao rodar teste: compile uma vez e rode sem recompilar (`dotnet test
95
- --no-build`); só os testes que a mudança toca (`--filter`) e, depois de
96
- uma falha, só os que falharam. Grave a saída em arquivo uma vez
97
- (`… > .morph/logs/test-last.log 2>&1`, sem nada depois) e leia o arquivo:
98
- rodar de novo com outro `| tail`/`| grep` repete o teste para ver outras
99
- linhas, e com pipe ou `; echo` o exit é o do último comando, não o do teste.
105
+ 3. TESTE — a prova é do orquestrador (`morph-spec verify {feature} {task}`,
106
+ logo depois do seu retorno), não sua. Escreva os testes pelo orçamento:
107
+ um por pós-condição, um de regressão por bug, variantes numa tabela
108
+ (`[Theory]`/`it.each`). NÃO rode teste a cada marco nem faça ciclo
109
+ red→green: escreva código e testes, compile, e rode SÓ o filtro dos seus
110
+ testes UMA vez, antes do relatório; se falhar, corrija e rode só os que
111
+ falharam. Em batch paralelo SEM isolamento, só compile — o teste roda no
112
+ verify pós-batch. Em batch COM `isolation: "worktree"`, o mesmo vale no
113
+ seu worktree, e o último ato antes do relatório é o commit na branch do
114
+ worktree — nunca faça merge; worktree não commitado NÃO é removido pelo
115
+ hook e vira pendência do `doctor`. Ao rodar: compile uma vez e rode sem
116
+ recompilar (`dotnet test --no-build`), com `--filter`. Grave a saída em
117
+ arquivo uma vez (`… > .morph/logs/test-last.log 2>&1`, sem nada depois)
118
+ e leia o arquivo: rodar de novo com outro `| tail`/`| grep` repete o teste
119
+ para ver outras linhas, e com pipe ou `; echo` o exit é o do último
120
+ comando, não o do teste.
100
121
 
101
122
  4. ESCOPO: no máximo 3 tasks e ~4 arquivos por dispatch. Escopo maior falha e
102
123
  volta — fatie antes, não depois.
103
124
  5. SOBREVIVÊNCIA: o limite de turnos (`maxTurns`, no seu system prompt)
104
- corta sem aviso: commite `wip({taskId})` a cada marco (arquivo que
105
- compila, teste que passa), não só ao fim da task — e só os seus arquivos
125
+ corta sem aviso: commite `wip({taskId})` a cada marco (um arquivo ou
126
+ uma fatia coerente escrita — sem rodar teste para isso), não só ao fim da task — e só os seus arquivos
106
127
  (`git add <paths>`, nunca `-A`). Sem commit, a retomada recomeça do zero.
107
128
  A ~70% do limite, grave o relatório parcial no arquivo canônico: `PARCIAL`
108
129
  na 1ª linha, o feito e o que falta, sem auto-score. Depois siga ou pare,
@@ -112,6 +133,9 @@ Ao iniciar cada task de `tasks.json` — antes de escrever qualquer código. Nor
112
133
  sessões). Encerre dev server pelo PID que você mesmo subiu.
113
134
  7. RETORNO: o relatório no arquivo canônico é o retorno. `SendMessage` não é
114
135
  substituto do relatório e não deve ser chamado.
136
+ 8. MUTAÇÃO: nunca altere, reverta, mova ou apague código de produção para ver
137
+ um teste falhar (`sed`, `mv`, `git show HEAD:… >`, `git stash`, `git
138
+ checkout --`). A prova de que o teste morde é do avaliador no Gate 3.
115
139
 
116
140
  Seu relatório (no arquivo, e na mensagem final quando ela chega) deve conter
117
141
  APENAS: (1) o que foi feito em 2-3 frases, (2) arquivos modificados,
@@ -151,8 +175,8 @@ Ao iniciar cada task de `tasks.json` — antes de escrever qualquer código. Nor
151
175
  5. Implemente a tarefa seguindo o standard e a persona identificados.
152
176
  Se encontrar ambiguidade de escopo não coberta pelo mandate, registre no decisions.md
153
177
  e resolva da forma mais conservadora — não pause para perguntar, a menos que seja bloqueante.
154
- Testes rodados durante a implementação inline seguem o mesmo loop da cláusula 3 do template
155
- do passo 4 (compilar uma vez, `--filter`, saída em arquivo).
178
+ Testes rodados durante a implementação inline seguem a cláusula 3 do template do passo 4
179
+ (sem red→green, uma rodada do filtro no fim, saída em arquivo) e a 8 (sem mutação).
156
180
 
157
181
  **Task com `3-implement/evidencias/{ID}.md` em `outputs`** (critério sobre saída de LLM —
158
182
  `morph-plan` §5): rode o eval ANTES de marcar `done` — e só o eval. Com nó `runner: "evals"`
@@ -241,7 +265,7 @@ Ao iniciar cada task de `tasks.json` — antes de escrever qualquer código. Nor
241
265
  > tasks.json + recap.md + `taskScores` do feature.json. **NÃO escreva o trace
242
266
  > manualmente** — a escrita manual foi removida da cerimônia por task.
243
267
 
244
- 9. Quando invocada por `morph-apply`, retornar o controle à skill orquestradora — ela decide qual task vem em seguida via `getReadyTasks(data)`. Não rode a suíte de testes inteira do projeto por conta própria ao fim da task quando invocada pela `morph-apply` — a verificação determinística (`morph-spec verify {feature} {task}`) é do orquestrador, logo após seu retorno (ver morph-apply §3a). **Única exceção:** a execução de evidência do passo 5 — só o nó `evals`, filtrado, com `--skip-e2e`, nunca persistida (`--no-persist`); ela não é a verificação da task e não substitui a do orquestrador. **A divisão:** no loop por task o recorte é **automático** — o `group` da task escolhe as suítes e os arquivos de teste dos `outputs` (passo 8) estreitam o comando dentro de cada uma (o relógio de uma task não paga a suíte inteira); `--filter {ids}` só força a escolha de suítes (um nó não casado aparece como `skip` nomeando o filtro, e um filtro que não casa nada é erro de uso, exit 2) e `--full` desliga o recorte. A suíte **inteira** roda no Gate 3 e no CI, sem filtro — `verify {feature}` nunca recorta. A suíte completa de um projeto grande não cabe numa invocação de Bash do harness — rode em background ou por partes, nunca "suba o limite" (não há constante de timeout global no CLI). Detalhe e forma de `project.tests[]`: `.morph/framework/CLI.md`, seção "Suítes de teste". Quando invocada manualmente, verificar se há próxima task ready e iniciá-la imediatamente aplicando esta skill desde o passo 1 (auto-advance). Pause apenas se encontrar ambiguidade bloqueante não coberta pelo mandate.
268
+ 9. Quando invocada por `morph-apply`, retornar o controle à skill orquestradora — ela decide qual task vem em seguida via `getReadyTasks(data)`. Não rode a suíte de testes inteira do projeto por conta própria ao fim da task quando invocada pela `morph-apply` — a verificação determinística (`morph-spec verify {feature} {task}`) é do orquestrador, logo após seu retorno (ver morph-apply §3a). **Única exceção:** a execução de evidência do passo 5 — só o nó `evals`, filtrado, com `--skip-e2e`, nunca persistida (`--no-persist`); ela não é a verificação da task e não substitui a do orquestrador. **A divisão:** no loop por task o recorte é **automático** — o `group` da task escolhe as suítes e os arquivos de teste dos `outputs` (passo 8) estreitam o comando dentro de cada uma (o relógio de uma task não paga a suíte inteira); `--filter {ids}` só força a escolha de suítes (um nó não casado aparece como `skip` nomeando o filtro, e um filtro que não casa nada é erro de uso, exit 2) e `--full` desliga o recorte. O sub-agent despachado roda só o filtro dos próprios testes, uma vez (cláusula 3), e nunca o `verify`. A suíte **inteira** roda no Gate 3 e no CI, sem filtro — `verify {feature}` nunca recorta. A suíte completa de um projeto grande não cabe numa invocação de Bash do harness — rode em background ou por partes, nunca "suba o limite" (não há constante de timeout global no CLI). Detalhe e forma de `project.tests[]`: `.morph/framework/CLI.md`, seção "Suítes de teste". Quando invocada manualmente, verificar se há próxima task ready e iniciá-la imediatamente aplicando esta skill desde o passo 1 (auto-advance). Pause apenas se encontrar ambiguidade bloqueante não coberta pelo mandate.
245
269
 
246
270
  ## Output esperado
247
271
  - Código implementado conforme o standard consultado (direto ou via sub-agent)
@@ -4,7 +4,7 @@ description: Conduz a AUTORIA de mídia gerada por IA — escolher o modelo pelo
4
4
  version: core
5
5
  when-to-invoke: quando a tarefa é PRODUZIR imagem ou vídeo por IA (catálogo, marketing, asset de LP) e alguém precisa decidir modelo, prompt e aprovação
6
6
  user-invokable: true
7
- cliVersion: "8.38.0"
7
+ cliVersion: "8.41.0"
8
8
  stacks:
9
9
  - dotnet
10
10
  - nextjs
@@ -212,4 +212,4 @@ trabalho de design". Tratar a saída como entregável vetorial é o erro clássi
212
212
 
213
213
  - Os cinco standards da tabela do topo — a fonte de API, custo, prazo e conformidade.
214
214
  - Proveniência do conhecimento absorvido: `.morph/framework/standards/PROVENANCE.json`
215
- (`gemini-image`, `cinematic-lp`, `brand-design`).
215
+ (`morph-image`, `cinematic-lp`, `brand-design`).
@@ -4,7 +4,7 @@ description: Guia a produção dos artefatos de planejamento de uma feature (use
4
4
  version: core
5
5
  when-to-invoke: ao iniciar a fase plan de uma feature, após o Gate 1 (proposal aprovado)
6
6
  user-invokable: true
7
- cliVersion: "8.38.0"
7
+ cliVersion: "8.41.0"
8
8
  ---
9
9
 
10
10
  # morph-plan
@@ -220,8 +220,9 @@ Ao iniciar a fase plan — após o `proposal.md` ser aprovado e antes de qualque
220
220
  proibidos: o orçamento por task do passo 5 (um teste por pós-condição + um de regressão por
221
221
  bug, justificativa acima disso, tabela antes de cópia, nenhum teste que só fixa texto);
222
222
  fixture compartilhada antes de helper novo; TDD onde paga (bug: regressão primeiro; lógica
223
- pura), teste depois aceito em UI e integração; comentário só com o porquê que o código não
224
- mostra, nunca história de task/UC/ADR. Nos standards obrigatórios, liste
223
+ pura), teste depois aceito em UI e integração; comentário: o padrão é nenhum (nome, tipo e teste
224
+ explicam), só o porquê que o código não mostra, nunca `///`/JSDoc que repete a assinatura
225
+ nem história de task/UC/ADR. Nos standards obrigatórios, liste
225
226
  `architecture-code-comments` e o standard de teste do stack (seção *Test budget*).
226
227
  - **Baseline é um COMANDO, nunca um número.** O mandate congela no Gate 2 e é lido por
227
228
  implementadores durante dias — todo número cravado nele (`Suíte: 2366 passando`, cobertura,
@@ -307,6 +308,12 @@ Ao iniciar a fase plan — após o `proposal.md` ser aprovado e antes de qualque
307
308
 
308
309
  **Preencha `outputs` (paths planejados) em cada task** — o `morph-spec dag` usa os outputs para detectar colisão de arquivos entre fluxos paralelos e recomendar `isolation: "worktree"`. Task sem `outputs` entra como footprint desconhecido (não força isolamento, mas o dag não consegue protegê-la de colisão).
309
310
 
311
+ **Tamanho da task: no máximo 8 `outputs`** (testes incluídos). Uma task inteira cabe num
312
+ dispatch; acima disso o sub-agente bate no teto de turnos e a retomada recomeça fria. Fatie por
313
+ pós-condição (uma task por pós-condição ou par delas, com a dependência explícita). Antes do
314
+ Gate 2, o `morph-spec dag` recusa (exit 1) e o `gate-check plan` pausa com `oversizedTasks`;
315
+ depois do Gate 2 é só aviso.
316
+
310
317
  **Critério sobre saída de LLM vira eval de runtime — nunca "suíte estrutural".** Duas etapas,
311
318
  como na `morph-review`: (1) **filtro mecânico** — o `mandate.md` cita ao menos um standard
312
319
  `ai-agents`; senão, a regra não se aplica. (2) **determinação sua, por task** — o
@@ -4,7 +4,7 @@ description: Orquestra a fase de proposta+plano de uma feature morph-spec. Encad
4
4
  version: core
5
5
  when-to-invoke: ao receber instrução "use /morph-proposal" do usuário, ou ao iniciar uma nova feature
6
6
  user-invokable: true
7
- cliVersion: "8.38.0"
7
+ cliVersion: "8.41.0"
8
8
  ---
9
9
 
10
10
  # morph-proposal
@@ -4,7 +4,7 @@ description: Conduz a fase de revisão e produz o review-report.md para o Gate 3
4
4
  version: core
5
5
  when-to-invoke: ao iniciar a fase review, após todas as tasks de tasks.json estarem com status `done`
6
6
  user-invokable: true
7
- cliVersion: "8.38.0"
7
+ cliVersion: "8.41.0"
8
8
  ---
9
9
 
10
10
  # morph-review
@@ -4,7 +4,7 @@ description: Varre o codebase existente, detecta stack atual, compara com o stac
4
4
  version: core
5
5
  when-to-invoke: ao iniciar uma feature em projeto brownfield (codebase já existente)
6
6
  user-invokable: true
7
- cliVersion: "8.38.0"
7
+ cliVersion: "8.41.0"
8
8
  ---
9
9
 
10
10
  # morph-stack-scan
@@ -4,7 +4,7 @@ description: Localiza um standard específico via busca server-side (morph-spec
4
4
  version: core
5
5
  when-to-invoke: quando precisar consultar um standard específico durante a implementação
6
6
  user-invokable: true
7
- cliVersion: "8.38.0"
7
+ cliVersion: "8.41.0"
8
8
  ---
9
9
 
10
10
  # morph-standards
@@ -4,7 +4,7 @@ description: Conduz a fase opcional de UI/UX — design system, mockups, compone
4
4
  version: core
5
5
  when-to-invoke: ao tomar o ramo uiux (morph-spec advance --design), depois do Gate 1 e antes do morph-plan
6
6
  user-invokable: true
7
- cliVersion: "8.38.0"
7
+ cliVersion: "8.41.0"
8
8
  ---
9
9
 
10
10
  # morph-uiux
@@ -32,11 +32,11 @@ Ao tomar o ramo opcional uiux: feature/bug cuja mudança cria ou altera superfí
32
32
  - **Sistemas, não telas isoladas** — mesmo critério da persona `ui-designer`: componentes reutilizáveis antes de composições de uso único.
33
33
  - **Toda tela sai com o checklist de tela preenchido** (template no passo 3) — a superfície, o volume esperado de dados, paginação, ordenação, filtro, os três estados (vazio, carregando, erro), o comportamento no mobile e abas × página longa. "Não se aplica" vale, **desde que escrito**. É o checklist que faz a lista de 2 000 linhas paginar: o que o design não decide não vira `doneCriteria` (`morph-plan` §5d), e o que não é critério ninguém entrega. Tela de dados segue os standards de `admin-app` (lista/tabela, formulário, feedback, estrutura de página), que a persona cita na superfície `admin-app`.
34
34
 
35
- 3. **Despache `morph-ui-designer`** para o trabalho visual — dispatch é o default aqui (domínio diferente do Orchestrator, MORPH.md §6). `morph-ui-designer` tem `Read/Write/Edit/Glob/Grep` + MCPs `stitch`/`gemini-image`/`playwright`/`context7`, mas **não tem Bash** — não peça build, testes nem `morph-spec` a ele; isso é do orquestrador.
35
+ 3. **Despache `morph-ui-designer`** para o trabalho visual — dispatch é o default aqui (domínio diferente do Orchestrator, MORPH.md §6). `morph-ui-designer` tem o escopo das implementadoras (com Bash) + `Skill` + MCPs `stitch`/`playwright`/`context7`/`graphify` + o MCP de mídia morph-assets (imagem e vídeo). Bash serve para `morph-spec standards --find`, `npx`, screenshot e leitura de `git`; build/test da suíte, `verify` e aprovação de gate continuam do orquestrador (cláusula 3, como nas outras personas).
36
36
 
37
37
  **Persona universal** (`ui-designer.stack = ["*"]` em `agents.json`, mesmo mecanismo de `evaluator`/`scout`): UI/UX importa sempre que há superfície de UI, então o subagent está registrado em **todo** projeto — .NET/Blazor incluído, não só Next.js. **Fallback** (caso raro: instalação anterior a essa mudança, `.claude/agents/morph-ui-designer.md` ainda não regenerado): `general-purpose` colando o campo `persona` (Read em `.morph/framework/agents.json`) no prompt, registrando o fallback no relatório — resolvido rodando `morph-spec setup-infra --reinstall`.
38
38
 
39
- Template do prompt (contrato do relatório em forma curta — copia o padrão de `morph-implement` §4, sem a cláusula de build/isolamento, que não se aplica a um agente sem Bash):
39
+ Template do prompt (contrato do relatório em forma curta — copia o padrão de `morph-implement` §4; a cláusula de build/isolamento vira "sem build/test da suíte", porque o design não entrega código a verificar):
40
40
  ```
41
41
  Produzir os artefatos de UI/UX de [feature] em `.morph/features/{feature}/1-design/`.
42
42
 
@@ -46,7 +46,7 @@ Ao tomar o ramo opcional uiux: feature/bug cuja mudança cria ou altera superfí
46
46
  Produza, NESTA ORDEM — design-system.md primeiro, os demais só como aplicável ao escopo:
47
47
  1. `design-system.md` — tokens (cor, tipografia, espaço, motion) consistentes com o projeto
48
48
  2. `mockups.md` — descrição estruturada de cada tela nova/alterada (+ imagem via MCP
49
- gemini-image/stitch quando disponível; fallback: descrição textual detalhada).
49
+ stitch ou o MCP de mídia (imagem/vídeo) quando disponível; fallback: descrição textual detalhada).
50
50
  Cada tela é um `## Tela: <nome>` e traz, dentro dela, o checklist abaixo, com cada `…`
51
51
  trocado pela decisão — "não se aplica" vale se escrito; `…`, vazio ou "a definir" não.
52
52
  O que cada item decide: Superfície (admin-app | marketing-site — ela escolhe que
@@ -82,8 +82,9 @@ Ao tomar o ramo opcional uiux: feature/bug cuja mudança cria ou altera superfí
82
82
  `1-design/reports/[artefato]-report.md` (ex.: `1-design/reports/design-system-report.md`)
83
83
  ANTES de encerrar — é o retorno autoritativo, não a sua mensagem final (cortesia
84
84
  best-effort, pode não chegar inteira). NÃO chame SendMessage.
85
- 2. Você não tem Bash — não rode `morph-spec`, build nem testes; a aprovação do Gate uiux
86
- e qualquer comando CLI são do orquestrador.
85
+ 2. Bash só para consulta (`morph-spec standards --find`, `npx`, screenshot, `git log/diff`):
86
+ NÃO rode build, testes nem `morph-spec verify`/`approve`/`advance` — a verificação e a
87
+ aprovação do Gate uiux são do orquestrador.
87
88
  3. NÃO toque em tasks.json, feature.json, state.json nem no board de sessão.
88
89
 
89
90
  Cada relatório contém: (1) o que foi feito em 2-3 frases, (2) o artefato produzido,
@@ -38,13 +38,13 @@
38
38
  "skills": []
39
39
  },
40
40
  {
41
- "id": "gemini-image",
41
+ "id": "morph-image",
42
42
  "repo": "morph-HUB",
43
- "path": "skills/gemini-image",
43
+ "path": "skills/morph-image",
44
44
  "envVar": "MORPH_HUB",
45
45
  "defaultCheckout": "R:/Polymorphism Tech/repos/morph-HUB",
46
- "sourceTree": "ec0abd827badfd5cd6d4c5f8b1843f81a3d183fe",
47
- "sourceCommit": "b6bbfff",
46
+ "sourceTree": "e55dcf307278583120601c3c5d55118302335f7b",
47
+ "sourceCommit": "c4c9164",
48
48
  "distilledOn": "2026-09-09",
49
49
  "distilledFrom": [
50
50
  "SKILL.md"
@@ -1551,7 +1551,7 @@
1551
1551
  "errorbody": "#rule-2--error-path-tests-assert-the-response-body-not-just-the-status-code",
1552
1552
  "test-budget": "#test-budget"
1553
1553
  },
1554
- "digest": "Inject TimeProvider (never DateTime.UtcNow / DateOnly.FromDateTime(DateTime.UtcNow) directly in a handler or validator) and fake it with FakeTimeProvider (Microsoft.Extensions.TimeProvider.Testing) in integration tests — deterministic, no midnight-UTC flake, boundary dates (today vs. yesterday) become facts about the fake clock instead of when the suite happens to run. xUnit + WebApplicationFactory error-path tests (400/404/409) must assert the ProblemDetails response BODY (title/detail/violated field or error code), never just the HTTP status code — a status-only assertion lets the wrong validation rule or the wrong error branch pass silently as long as the status matches. Test budget per task: one test per postcondition plus one regression test per bug, more only with a one-line justification in the task; scenarios of the same behavior (edge cases included) are rows of one [Theory], never copied [Fact]s; no test whose only assertion is a copy, config or prose string (that is an analyzer or a publish-time validation, outside the suite count); shared fixtures before new helpers; TDD for bugs (regression first) and pure logic; a surviving mutant is killed by tightening an assertion or adding a row, not by a new test.",
1554
+ "digest": "Inject TimeProvider (never DateTime.UtcNow / DateOnly.FromDateTime(DateTime.UtcNow) directly in a handler or validator) and fake it with FakeTimeProvider (Microsoft.Extensions.TimeProvider.Testing) in integration tests — deterministic, no midnight-UTC flake, boundary dates (today vs. yesterday) become facts about the fake clock instead of when the suite happens to run. xUnit + WebApplicationFactory error-path tests (400/404/409) must assert the ProblemDetails response BODY (title/detail/violated field or error code), never just the HTTP status code — a status-only assertion lets the wrong validation rule or the wrong error branch pass silently as long as the status matches. Test budget per task: one test per postcondition plus one regression test per bug, more only with a one-line justification in the task; scenarios of the same behavior (edge cases included) are rows of one [Theory], never copied [Fact]s; no test whose only assertion is a copy, config or prose string (that is an analyzer or a publish-time validation, outside the suite count); shared fixtures before new helpers; bugs and pure logic get tests in any order — the implementer runs its own filter once, never red-green cycles nor production mutation (the Gate 3 mutation proof shows the test bites); a surviving mutant is killed by tightening an assertion or adding a row, not by a new test.",
1555
1555
  "verifiedAgainst": ".NET 10 + xUnit 2 + `Microsoft.Extensions.TimeProvider.Testing`.",
1556
1556
  "provedBy": []
1557
1557
  },
@@ -1850,8 +1850,8 @@
1850
1850
  "favicon-og": "#the-two-assets-everyone-forgets",
1851
1851
  "variations": "#variations-and-cost"
1852
1852
  },
1853
- "digest": "Guidelines for generating project images with the Gemini Image MCP: when to use AI versus stock versus SVG, prompt patterns, aspect ratios, iterative editing and assets.md format. Core principle is brand fidelity over invention: always pass the client's real assets as referenceImages via edit_image rather than generating in a vacuum, never AI-recreate a property developer's architectural render or a physical product (animate or reference the real one), and chain derivatives from an approved hero so the whole set shares light, palette and identity. Frame anything destined to become video WITHOUT a face, because video moderation is stricter (E005), and generate scrub frames at the video's exact ratio with the subject opposite the copy. Always produce the two forgotten assets: a favicon derived from the real logo (never a new one) and a 1200x630 OG share image. Offer two to three genuinely different variations per image, varying angle, light or composition rather than the seed, and never advance with a weak image because every derivative inherits it.",
1854
- "verifiedAgainst": "Gemini Image MCP + Next.js 15 `next/image`.",
1853
+ "digest": "Guidelines for generating project images with the morph-assets MCP (OpenRouter; default openai/gpt-image-2.5-flare, drafts on mai-image-2.6-flash, gemini-3.1-flash-image for 2K/4K or 6-14 refs; models: [...] compares): when to use AI versus stock versus SVG, prompt patterns, aspect ratios, iterative editing and assets.md format. Core principle is brand fidelity over invention: always pass the client's real assets as references (or @brand with a project) via edit_image rather than generating in a vacuum, never AI-recreate a property developer's architectural render or a physical product (animate or reference the real one), and chain derivatives from an approved hero so the whole set shares light, palette and identity. Frame anything destined to become video WITHOUT a face, because video moderation is stricter (E005), and generate scrub frames at the video's exact ratio with the subject opposite the copy. Always produce the two forgotten assets: a favicon derived from the real logo (never a new one) and a 1200x630 OG share image. Offer two to three genuinely different variations per image (variants returns a contact sheet), varying angle, light or composition since seed is not supported by the GPT Image/Gemini models, and never advance with a weak image because every derivative inherits it. Copy to render goes between double quotes; CONFIRMATION_REQUIRED needs human approval and a confirmToken.",
1854
+ "verifiedAgainst": "morph-assets MCP (OpenRouter; default model `openai/gpt-image-2.5-flare`) + Next.js 15 `next/image`.",
1855
1855
  "provedBy": []
1856
1856
  },
1857
1857
  {
@@ -1889,8 +1889,8 @@
1889
1889
  "cost-ladder": "#section-4-the-cost-ladder",
1890
1890
  "prompt-skeleton": "#section-5-prompt-skeleton"
1891
1891
  },
1892
- "digest": "The decisive rule: a perfect loop has an end frame identical to its start, which is right for a self-playing ambient background and WRONG for scroll scrubbing, because start and end look the same and the page reads as frozen while the user scrolls. Scroll-driven footage needs directional movement via generate_video with an endImage (push-in/dolly is the most reliable, then reveal, pull-back, slow tilt); avoid orbits and any movement that returns to its origin. Client architectural renders are animated with img2vid, never AI-recreated. Human faces repeatedly trip moderation (E005), so crop the face out of frame (neck down, hands, product) and reserve faces for static image generation. Always climb the cost ladder: fast/480p/4s draft to judge framing and movement, 1080p only after approval, then re-extract frames with a bumped cache-bust. Prompts read like director notes with no hype words, and must reserve a calm dark region for the page copy with the subject on the opposite side. Generation is async: generate_video returns a request_id polled via get_video; list_videos reads local history and spends no credits.",
1893
- "verifiedAgainst": "seedance MCP (generate_video, generate_loop_video, get_video, list_videos) over Replicate.",
1892
+ "digest": "The decisive rule: a perfect loop has an end frame identical to its start, which is right for a self-playing ambient background and WRONG for scroll scrubbing, because start and end look the same and the page reads as frozen while the user scrolls. Scroll-driven footage needs directional movement via generate_video with an endImage (push-in/dolly is the most reliable, then reveal, pull-back, slow tilt); avoid orbits and any movement that returns to its origin. Client architectural renders are animated with img2vid, never AI-recreated. Human faces repeatedly trip moderation (E005), so crop the face out of frame (neck down, hands, product) and reserve faces for static image generation. Always climb the cost ladder: seedance-1-5-pro 480p draft to judge framing and movement, then promoteFrom to seedance-2.0 1080p only after approval (same prompt, frames and seed), then re-extract frames with a bumped cache-bust. seedance-2.0-mini does NOT respect endImage and Veo 3.1 Lite/Fast are inconclusive, so scrub only on Seedance 1.5 Pro/2.0 and check the last-frame SSIM QA. Video has no ZDR on OpenRouter: nothing sensitive in the frames. Prompts read like director notes with no hype words, and must reserve a calm dark region for the page copy with the subject on the opposite side. Generation is async via the morph-assets MCP (OpenRouter): a running job is polled with get_video (several ids at once), never by resending generate_video; library reads local history and spends no credits; media_tool extracts scrub frames and posters.",
1893
+ "verifiedAgainst": "morph-assets MCP (generate_video, generate_loop_video, get_video, library, media_tool) over OpenRouter; models `bytedance/seedance-1-5-pro` and `bytedance/seedance-2.0`.",
1894
1894
  "provedBy": []
1895
1895
  },
1896
1896
  {
@@ -2371,7 +2371,7 @@
2371
2371
  "e2e": "#test-file-co-location",
2372
2372
  "test-budget": "#test-budget"
2373
2373
  },
2374
- "digest": "Vitest for unit tests, React Testing Library for component tests. Mock next/navigation with vi.mock. Test Server Actions with direct function calls. Use MSW for API mocking in component tests. Playwright for E2E tests against running app. Never test implementation details — test user behavior and output. Test budget per task: one test per postcondition plus one regression test per bug, more only with a one-line justification in the task; scenarios of the same behavior are rows of one it.each, never copied it() blocks; no test whose only assertion is a copy string (lint or publish-time validation instead); shared wrappers, MSW handlers and factories before new helpers; TDD for bugs and pure logic, component tests may come after the code.",
2374
+ "digest": "Vitest for unit tests, React Testing Library for component tests. Mock next/navigation with vi.mock. Test Server Actions with direct function calls. Use MSW for API mocking in component tests. Playwright for E2E tests against running app. Never test implementation details — test user behavior and output. Test budget per task: one test per postcondition plus one regression test per bug, more only with a one-line justification in the task; scenarios of the same behavior are rows of one it.each, never copied it() blocks; no test whose only assertion is a copy string (lint or publish-time validation instead); shared wrappers, MSW handlers and factories before new helpers; bugs and pure logic get tests in any order — the implementer runs its own filter once, never red-green cycles nor production mutation.",
2375
2375
  "verifiedAgainst": "Vitest 3 + React Testing Library 16 + MSW 2.",
2376
2376
  "provedBy": []
2377
2377
  },
@@ -2689,8 +2689,8 @@
2689
2689
  "tools": "#mcp-providers-by-phase",
2690
2690
  "setup": "#mcp-availability-detection"
2691
2691
  },
2692
- "digest": "MCP tools extend Claude with external data and actions. Tools are synchronous request-response with typed inputSchema. Resources provide read-only data access. Prompts are reusable templates. Register MCP servers in .claude/settings.json. Prefer @context7 for live library docs. Test tools with MCP Inspector before integrating.",
2693
- "verifiedAgainst": "Claude Code MCP tooling — context7, Playwright; GitHub via `gh` CLI; Neon via `neonctl`.",
2692
+ "digest": "MCP tools extend Claude with external data and actions. Tools are synchronous request-response with typed inputSchema. Resources provide read-only data access. Prompts are reusable templates. Register MCP servers in .claude/settings.json. Prefer @context7 for live library docs. Tool names follow where the server is configured: mcp__context7__query-docs from .mcp.json, mcp__plugin_context7_context7__query-docs from the plugin; a deferred tool loads via ToolSearch. Test tools with MCP Inspector before integrating.",
2693
+ "verifiedAgainst": "Claude Code 2.1.282 MCP tooling — context7, Playwright (as plugin and as a project MCP server); GitHub via `gh` CLI; Neon via its MCP or `neonctl`.",
2694
2694
  "provedBy": []
2695
2695
  },
2696
2696
  {
@@ -2848,7 +2848,7 @@
2848
2848
  "not-worth": "#o-que-não-merece",
2849
2849
  "size": "#tamanho"
2850
2850
  },
2851
- "digest": "Comment only the WHY the code cannot show: an invariant the type does not express, an order that matters, an external quirk (third-party API, library bug with its link), a public API contract. Never process history: task, UC, ADR, FR, Gate, evaluator, spec.md and mockup belong in the commit message and decisions.md. Do not restate the code (a good name replaces the comment), do not describe the world outside the file (it goes stale), and turn claims about behavior into test assertions. Ceiling ~3 lines; longer needs a reason. The verify validators node (code-budget) warns with the count of added comment lines that cite process.",
2851
+ "digest": "Default is NO comment: code explains itself through names, types and tests. Before commenting, rename, extract a function or named constant, encode the state in the type, or write a test; comment only what none of these can express: an invariant the type does not express, an order that matters, an external quirk (third-party API, library bug with its link), or the contract of a package published for consumers outside the repo. Never process history (task, UC, ADR, FR, Gate, evaluator, spec.md, mockup: commit message and decisions.md), never restate the code, no XML doc/JSDoc on application members that repeats the signature, no file headers, section banners, #region, commented-out code or loose TODOs, no claims about behavior (make them test assertions). One line is normal, ~3 is the ceiling; more than one comment line per ten code lines means the names are not doing the work. The verify validators node (code-budget) warns on added comments that cite process and on added comment density.",
2852
2852
  "verifiedAgainst": "C#, TypeScript e JavaScript (convenção de linguagem, sem pacote externo).",
2853
2853
  "provedBy": []
2854
2854
  }
@@ -30,8 +30,7 @@ Preciso que o agente saiba X.
30
30
  Plano por fase (instruções + **allow-list de tools** conforme o estado do funil) **não** é caso de provider. É C# puro, montado antes de criar a requisição:
31
31
 
32
32
  ```csharp
33
- // O CÓDIGO decide o modo; o LLM só classifica. A allow-list de tools é a parte
34
- // que um provider não consegue dar: AIContext.Tools ACRESCENTA tools, não remove.
33
+ // A allow-list não cabe num provider: AIContext.Tools ACRESCENTA tools, não remove.
35
34
  public sealed record OperatorPlan(string Instructions, IReadOnlyList<AITool> Tools);
36
35
 
37
36
  public static OperatorPlan PlanFor(FunnelStage stage) => stage switch
@@ -92,10 +91,8 @@ Use um `AIContextProvider` quando o agente precisa de **contexto dinâmico compu
92
91
 
93
92
  **Método a sobrescrever:**
94
93
 
95
- ```csharp
96
- // ProvideAIContextAsync → chamado ANTES do LLM (before-run hook) — injeta contexto
97
- // StoreAIContextAsync → chamado APÓS o LLM (after-run hook) — persiste estado se necessário
98
- ```
94
+ - `ProvideAIContextAsync` → chamado ANTES do LLM (before-run hook) — injeta contexto
95
+ - `StoreAIContextAsync` → chamado APÓS o LLM (after-run hook) — persiste estado se necessário (opcional)
99
96
 
100
97
  ### A invariante de instância — a mesma de `ai-agents-agent-session`
101
98
 
@@ -122,32 +119,33 @@ Consequência prática: **compaction só faz sentido com histórico local**. Com
122
119
 
123
120
  ## Exemplo C# — context provider que injeta data atual e perfil do tenant
124
121
 
122
+ O bloco tem três partes: o provider, o registro do agente com o provider no DI (`Program.cs`) e o uso
123
+ normal. `ITenantContext` é implementado via `IHttpContextAccessor` ou `AsyncLocal` para resolver o
124
+ tenant em runtime, nunca registrado como instância estática. O contexto volta como instrução
125
+ adicional, não como mensagem do usuário, e `StoreAIContextAsync` fica vazio porque o provider é
126
+ stateless. No uso, o provider é invocado a cada `RunAsync`: o agente já sabe a data, o nome do tenant
127
+ e o idioma, sem código extra no caller.
128
+
125
129
  ```csharp
126
130
  using Microsoft.Agents.AI;
127
131
  using Microsoft.Extensions.AI;
128
132
 
129
- // ── 1. Definir o provider ──
130
133
  public sealed class TenantContextProvider : AIContextProvider
131
134
  {
132
135
  private readonly ITenantService _tenantService;
133
136
  private readonly ITenantContext _tenantContext;
134
137
 
135
- // ITenantContext deve ser implementado via IHttpContextAccessor ou AsyncLocal
136
- // para resolver o tenant atual em runtime — não registre como instância estática.
137
- // O AIAgent é singleton, então o provider também é singleton; o tenant corrente
138
- // é lido de forma ambient (IHttpContextAccessor/AsyncLocal) a cada chamada.
138
+ // Singleton como o AIAgent: o tenant corrente é lido ambient a cada chamada, nunca guardado.
139
139
  public TenantContextProvider(ITenantService tenantService, ITenantContext tenantContext)
140
140
  {
141
141
  _tenantService = tenantService;
142
142
  _tenantContext = tenantContext;
143
143
  }
144
144
 
145
- // Sobrescreva: injetado ANTES de cada chamada ao LLM
146
145
  protected override async ValueTask<AIContext> ProvideAIContextAsync(
147
146
  InvokingContext context,
148
147
  CancellationToken cancellationToken = default)
149
148
  {
150
- // Tenant resolvido via serviço injetado (ambient context, ex: IHttpContextAccessor)
151
149
  var tenantId = _tenantContext.TenantId ?? "unknown";
152
150
  var tenant = await _tenantService.GetTenantAsync(tenantId, cancellationToken);
153
151
 
@@ -159,20 +157,16 @@ public sealed class TenantContextProvider : AIContextProvider
159
157
 
160
158
  return new AIContext
161
159
  {
162
- // Injeta como instrução adicional — não como mensagem do usuário
163
160
  Instructions = instructions,
164
161
  };
165
162
  }
166
163
 
167
- // Sobrescreva (opcional): chamado APÓS o LLM — use para persistir estado derivado da resposta
168
164
  protected override ValueTask StoreAIContextAsync(
169
165
  InvokedContext context,
170
166
  CancellationToken cancellationToken = default)
171
- => ValueTask.CompletedTask; // stateless provider — nada a persistir
167
+ => ValueTask.CompletedTask;
172
168
  }
173
169
 
174
- // ── 2. Registrar o agente com o provider no DI ──
175
- // Program.cs
176
170
  builder.Services.AddSingleton<AIAgent>(sp =>
177
171
  {
178
172
  var registry = sp.GetRequiredService<ModelRegistry>();
@@ -187,19 +181,15 @@ builder.Services.AddSingleton<AIAgent>(sp =>
187
181
  });
188
182
  });
189
183
 
190
- // ── Alternativa: pipeline de chat (compacta/injeta SÓ o request em voo) ──
191
- // using Microsoft.Extensions.AI; // a extensão vive na assembly Microsoft.Agents.AI
192
- // IChatClient enriched = chatClient.AsBuilder()
193
- // .UseAIContextProviders(new TenantContextProvider(tenantSvc, tenantContext))
194
- // .Build();
195
-
196
- // ── 3. Uso normal — provider é invocado automaticamente a cada RunAsync ──
197
184
  AgentSession session = await agent.CreateSessionAsync();
198
185
  AgentResponse response = await agent.RunAsync("Quais são meus benefícios do plano?", session);
199
186
  Console.WriteLine(response.Text);
200
- // O agente já sabe a data, o nome do tenant e o idioma — sem código extra no caller
201
187
  ```
202
188
 
189
+ **Alternativa: pipeline de chat**, que compacta/injeta **só** o request em voo: registre o provider
190
+ com `.UseAIContextProviders(...)` no `ChatClientBuilder` (`chatClient.AsBuilder()`). O `using` é
191
+ `Microsoft.Extensions.AI`, mas a extensão vive na assembly `Microsoft.Agents.AI`.
192
+
203
193
  ---
204
194
 
205
195
  ## Context Provider vs Tools vs RAG
@@ -22,12 +22,11 @@ If neither applies, a plain workflow (or no workflow at all — see `ai-agents-s
22
22
 
23
23
  ## Human-in-the-Loop via `RequestPort`
24
24
 
25
- HITL is modeled with `RequestPort` — a special node in the workflow graph that pauses execution and waits for an external (human) response instead of processing automatically.
25
+ HITL is modeled with `RequestPort` — a special node in the workflow graph that pauses execution and waits for an external (human) response instead of processing automatically. Its two type arguments are the request type the port sends out and the response type it expects back.
26
26
 
27
27
  ```csharp
28
28
  using Microsoft.Agents.AI.Workflows;
29
29
 
30
- // Request type the port sends out, response type it expects back.
31
30
  RequestPort<ApprovalRequest, bool> approvalPort =
32
31
  RequestPort.Create<ApprovalRequest, bool>("RefundApproval");
33
32
 
@@ -47,8 +46,7 @@ await foreach (WorkflowEvent evt in run.WatchStreamAsync())
47
46
  switch (evt)
48
47
  {
49
48
  case RequestInfoEvent requestEvt:
50
- // Surface requestEvt.Request to a human (dashboard, email, Slack, ...).
51
- // This is where execution pauses until an external answer arrives.
49
+ // Execution pauses here until the human's answer arrives (dashboard, email, Slack, ...).
52
50
  bool approved = await GetHumanDecisionAsync(requestEvt.Request);
53
51
  await run.SendResponseAsync(requestEvt.Request.CreateResponse(approved));
54
52
  break;
@@ -77,8 +75,14 @@ O caso do agente único é o que a casa realmente tem (MORPH_OS: billing, envio
77
75
 
78
76
  ### O ciclo, medido em `Microsoft.Extensions.AI` 10.9.0
79
77
 
78
+ Quatro passos: (1) embrulhe a tool — `ApprovalRequiredAIFunction : DelegatingAIFunction`; (2) o run
79
+ **termina** pedindo aprovação — não bloqueia, não espera —, e `ToolApprovalRequestContent.ToolCall` é
80
+ um `ToolCallContent` (medido; **não** é `FunctionCallContent`, que aparece em
81
+ `ToolAutoApprovalRuleContext`); (3) responda **na mesma sessão**, com
82
+ `CreateResponse(bool approved, string? reason)`; (4) **repita** o passo 2 até não restar pendência —
83
+ uma volta pode pedir **outra** tool.
84
+
80
85
  ```csharp
81
- // 1. Embrulhe a tool. ApprovalRequiredAIFunction : DelegatingAIFunction.
82
86
  AIFunction charge = AIFunctionFactory.Create(BillingTools.ChargeCustomer);
83
87
  AITool guarded = new ApprovalRequiredAIFunction(charge);
84
88
 
@@ -88,22 +92,16 @@ AIAgent agent = registry.GetChatClient("text-default")
88
92
  AgentSession session = await agent.CreateSessionAsync();
89
93
  AgentResponse response = await agent.RunAsync("Cobre o cliente 42.", session);
90
94
 
91
- // 2. O run TERMINA pedindo aprovação — não bloqueia, não espera.
92
- // ToolApprovalRequestContent.ToolCall é um ToolCallContent (medido; NÃO é
93
- // FunctionCallContent — este último aparece em ToolAutoApprovalRuleContext).
94
95
  var pending = response.Messages
95
96
  .SelectMany(m => m.Contents)
96
97
  .OfType<ToolApprovalRequestContent>()
97
98
  .ToList();
98
99
 
99
- // 3. Responda NA MESMA SESSÃO. CreateResponse(bool approved, string? reason).
100
100
  if (pending.Count > 0)
101
101
  {
102
102
  var approvals = pending.Select(r => (AIContent)r.CreateResponse(approved: true, reason: "aprovado por lucas@…"));
103
103
  response = await agent.RunAsync(new ChatMessage(ChatRole.User, [.. approvals]), session);
104
104
  }
105
-
106
- // 4. REPITA o passo 2 até não restar pendência. Uma volta pode pedir OUTRA tool.
107
105
  ```
108
106
 
109
107
  **Os quatro pontos que erram na primeira tentativa:**
@@ -157,10 +155,11 @@ Checkpointing is part of the **base, GA** `Microsoft.Agents.AI.Workflows` namesp
157
155
  | `CheckpointManager.CreateJson(new FileSystemJsonCheckpointStore(dir))` | Local disk, survives process restart | Single-instance VPS deployments — no Azure, no preview package |
158
156
  | Custom `ICheckpointStore` implementation | Whatever backend you implement it against | **Recommended for production** — implement against the project's own Neon Postgres table, matching the ownership model already used by `ai-agents-rag-custom-pgvector` |
159
157
 
158
+ Local-disk durability, with no Azure dependency:
159
+
160
160
  ```csharp
161
161
  using Microsoft.Agents.AI.Workflows;
162
162
 
163
- // Local-disk durability — no Azure dependency:
164
163
  var checkpointFolder = Directory.CreateDirectory("./checkpoints");
165
164
  CheckpointManager checkpointManager = CheckpointManager.CreateJson(
166
165
  new FileSystemJsonCheckpointStore(checkpointFolder));
@@ -171,13 +170,12 @@ await foreach (WorkflowEvent evt in run.WatchStreamAsync())
171
170
  if (evt is SuperStepCompletedEvent stepEvt)
172
171
  {
173
172
  CheckpointInfo? checkpoint = stepEvt.CompletionInfo?.Checkpoint;
174
- // Persist checkpoint.CheckpointId alongside the business record
175
- // (e.g. the refund request row) so it can be resumed after a restart.
173
+ // Persist checkpoint.CheckpointId with the business record (e.g. the refund row) to resume after a restart.
176
174
  }
177
175
  }
178
176
  ```
179
177
 
180
- Resuming after a restart — rehydrate into a **new** run instance from the last known checkpoint:
178
+ Resuming after a restart — rehydrate into a **new** run instance from the last known checkpoint. A pending `RequestPort` request is re-emitted as a `RequestInfoEvent`, so the paused approval survives the restart:
181
179
 
182
180
  ```csharp
183
181
  StreamingRun resumedRun = await InProcessExecution.ResumeStreamingAsync(
@@ -185,8 +183,6 @@ StreamingRun resumedRun = await InProcessExecution.ResumeStreamingAsync(
185
183
 
186
184
  await foreach (WorkflowEvent evt in resumedRun.WatchStreamAsync())
187
185
  {
188
- // A pending RequestPort request is re-emitted here as a RequestInfoEvent —
189
- // the paused approval survives the restart.
190
186
  if (evt is RequestInfoEvent requestEvt) { /* re-surface to the human */ }
191
187
  }
192
188
  ```
@@ -211,14 +207,12 @@ internal sealed class RefundAnalyzerExecutor() : Executor("RefundAnalyzer")
211
207
 
212
208
  ### `ICheckpointStore` — Neon/Postgres-backed (recommended production pattern)
213
209
 
214
- Implementing `ICheckpointStore` against the project's own Postgres database keeps checkpoint durability inside the same infrastructure the rest of the project already trusts (see `infrastructure-neon-setup`), instead of introducing a new storage dependency:
210
+ Implementing `ICheckpointStore` against the project's own Postgres database keeps checkpoint durability inside the same infrastructure the rest of the project already trusts (see `infrastructure-neon-setup`), instead of introducing a new storage dependency. The store persists and retrieves checkpoint blobs in a `workflow_checkpoints` table (`workflow_id`, `checkpoint_id`, `payload` jsonb/bytea, `created_at`), implemented per the `ICheckpointStore` contract in the `Microsoft.Agents.AI.Workflows` docs:
215
211
 
216
212
  ```csharp
217
213
  public sealed class PostgresCheckpointStore(NpgsqlDataSource dataSource) : ICheckpointStore
218
214
  {
219
- // Persist/retrieve checkpoint blobs in a workflow_checkpoints table
220
- // (workflow_id, checkpoint_id, payload jsonb/bytea, created_at).
221
- // Implement per the ICheckpointStore contract — see Microsoft.Agents.AI.Workflows docs.
215
+ // ICheckpointStore members over workflow_checkpoints — elided.
222
216
  }
223
217
  ```
224
218