@polymorphism-tech/morph-spec 8.34.2 → 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.
- package/CLAUDE.md +20 -3
- package/README.md +2 -2
- package/bin/morph-spec.js +18 -4
- package/bin/validate.js +379 -379
- package/claude-plugin.json +1 -1
- package/docs/CHEATSHEET.md +5 -4
- package/docs/QUICKSTART.md +1 -1
- package/framework/MORPH.md +16 -17
- package/framework/agents.json +197 -44
- package/framework/ai-pin.json +22 -0
- package/framework/commands/morph-media.md +45 -0
- package/framework/docs/CLI.md +234 -9
- package/framework/evals/proof-rubrics/README.md +76 -0
- package/framework/evals/proof-rubrics/eval-de-modelo.md +64 -0
- package/framework/evals/proof-rubrics/fiacao.md +54 -0
- package/framework/evals/proof-rubrics/guard-cego.md +52 -0
- package/framework/evals/proof-rubrics/media-claims.md +109 -0
- package/framework/evals/proof-rubrics/mutation-proof.md +77 -0
- package/framework/evals/proof-rubrics/observabilidade-genai.md +119 -0
- package/framework/evals/proof-rubrics/verde-nao-e-coberto.md +48 -0
- package/framework/evals/rubrics/architecture.md +30 -0
- package/framework/evals/rubrics/code-quality.md +26 -0
- package/framework/evals/rubrics/test-coverage.md +20 -0
- package/framework/hooks/claude-code/core/protect-spec-files.js +41 -4
- package/framework/hooks/claude-code/statusline.sh +11 -11
- package/framework/hooks/git/commit-msg/conventional-commits.sh +33 -33
- package/framework/hooks/git/pre-commit/agents.sh +25 -25
- package/framework/hooks/git/pre-commit/orchestrator.sh +64 -64
- package/framework/hooks/git/pre-commit/specs.sh +50 -50
- package/framework/hooks/git/pre-push/run-tests.sh +44 -44
- package/framework/hooks/shared/e2e-check.js +135 -22
- package/framework/hooks/shared/stdin-reader.js +26 -26
- package/framework/rules/ai-agents-standards.md +14 -2
- package/framework/schemas/ai-pin.schema.json +97 -0
- package/framework/schemas/config.schema.json +107 -0
- package/framework/schemas/feature.schema.json +23 -4
- package/framework/skills/core/create-umbraco-lp/SKILL.md +1 -1
- package/framework/skills/core/migrate-lp-to-umbraco/SKILL.md +1 -1
- package/framework/skills/core/morph-apply/SKILL.md +26 -5
- package/framework/skills/core/morph-brainstorming/SKILL.md +1 -1
- package/framework/skills/core/morph-eval/SKILL.md +1 -1
- package/framework/skills/core/morph-hotfix/SKILL.md +2 -2
- package/framework/skills/core/morph-implement/SKILL.md +18 -2
- package/framework/skills/core/morph-media/SKILL.md +215 -0
- package/framework/skills/core/morph-plan/SKILL.md +33 -2
- package/framework/skills/core/morph-proposal/SKILL.md +1 -1
- package/framework/skills/core/morph-review/SKILL.md +166 -9
- package/framework/skills/core/morph-stack-scan/SKILL.md +1 -1
- package/framework/skills/core/morph-standards/SKILL.md +1 -1
- package/framework/skills/core/morph-uiux/SKILL.md +1 -1
- package/framework/standards/PROVENANCE.json +81 -3
- package/framework/standards/STANDARDS.json +1483 -839
- package/framework/standards/ai-agents/agent-archetypes.md +160 -0
- package/framework/standards/ai-agents/agent-session.md +164 -68
- package/framework/standards/ai-agents/agent-spec.md +196 -0
- package/framework/standards/ai-agents/batching.md +61 -37
- package/framework/standards/ai-agents/context-providers.md +97 -24
- package/framework/standards/ai-agents/conversational-agent-with-phases.md +239 -0
- package/framework/standards/ai-agents/cost-and-budget.md +256 -0
- package/framework/standards/ai-agents/durable-workflows-hitl.md +98 -5
- package/framework/standards/ai-agents/evals-with-cache.md +289 -0
- package/framework/standards/ai-agents/guardrails.md +222 -0
- package/framework/standards/ai-agents/llm-runtime-defaults.md +226 -0
- package/framework/standards/ai-agents/mcp-server.md +119 -18
- package/framework/standards/ai-agents/mcp-tools.md +85 -32
- package/framework/standards/ai-agents/media-pipeline.md +352 -0
- package/framework/standards/ai-agents/media-video.md +267 -0
- package/framework/standards/ai-agents/middleware-patterns.md +39 -5
- package/framework/standards/ai-agents/modalities-image-gen.md +354 -105
- package/framework/standards/ai-agents/modalities-speech-to-text.md +8 -2
- package/framework/standards/ai-agents/modalities-text-to-speech.md +10 -2
- package/framework/standards/ai-agents/modalities-vision.md +6 -2
- package/framework/standards/ai-agents/multi-agent-patterns.md +61 -5
- package/framework/standards/ai-agents/observability-patterns.md +227 -17
- package/framework/standards/ai-agents/production.md +38 -9
- package/framework/standards/ai-agents/prompt-sources.md +389 -0
- package/framework/standards/ai-agents/providers/model-registry.md +174 -39
- package/framework/standards/ai-agents/rag-custom-pgvector.md +69 -4
- package/framework/standards/ai-agents/service-tier-flex.md +27 -19
- package/framework/standards/ai-agents/setup.md +166 -50
- package/framework/standards/ai-agents/structured-output.md +34 -3
- package/framework/standards/ai-agents/sweet-spot.md +23 -3
- package/framework/standards/ai-agents/testing-ai.md +236 -0
- package/framework/standards/ai-agents/vector-data-extensions.md +50 -20
- package/framework/standards/ai-agents/workflows.md +27 -7
- package/framework/standards/frontend/design-system/ai-image-generation.md +12 -0
- package/framework/standards/frontend/design-system/ai-video-generation.md +13 -0
- package/framework/standards/infrastructure/docker/local-compose-isolation.md +3 -1
- package/framework/templates/.idea/morph-templates.xml +92 -0
- package/framework/templates/.vscode/morph-templates.code-snippets +186 -0
- package/framework/templates/IDE-SNIPPETS.md +262 -262
- package/framework/templates/REGISTRY.json +13 -0
- package/framework/templates/code/dotnet/abstractions/api-endpoint.cs +7 -7
- package/framework/templates/code/dotnet/ai-agents/AgentBootstrap.cs.template +39 -39
- package/framework/templates/code/dotnet/ai-agents/EmbeddingService.cs.template +68 -68
- package/framework/templates/code/dotnet/ai-agents/ModelRegistry.cs.template +117 -117
- package/framework/templates/code/dotnet/ai-agents/PromptRepository.cs.template +1 -1
- package/framework/templates/code/dotnet/ai-agents/ResilientToolMiddleware.cs.template +61 -61
- package/framework/templates/code/dotnet/ai-agents/VectorSearchTool.cs.template +107 -107
- package/framework/templates/code/dotnet/ai-agents/model-registry.json.template +58 -58
- package/framework/templates/code/dotnet/contracts/contracts-vsa.cs +281 -281
- package/framework/templates/code/dotnet/database/migration.cs +83 -83
- package/framework/templates/code/dotnet/feature/endpoint.cs.hbs +21 -21
- package/framework/templates/code/dotnet/feature/request.cs.hbs +4 -4
- package/framework/templates/code/dotnet/feature/response.cs.hbs +4 -4
- package/framework/templates/code/dotnet/feature/validator.cs.hbs +15 -15
- package/framework/templates/code/sql/ai-agents/agent-prompts-migration.sql.template +1 -1
- package/framework/templates/code/sql/ai-agents/pgvector-embeddings-migration.sql.template +91 -91
- package/framework/templates/code/typescript/contracts.ts +167 -167
- package/framework/templates/docs/clarifications.md +253 -253
- package/framework/templates/docs/schema-analysis.md +119 -119
- package/framework/templates/docs/ui-components.md +52 -52
- package/framework/templates/docs/ui-design-system.md +76 -76
- package/framework/templates/docs/ui-flows.md +167 -167
- package/framework/templates/docs/ui-mockups.md +98 -98
- package/framework/templates/dotnet/ai-kit/Directory.Build.props +25 -0
- package/framework/templates/dotnet/ai-kit/Directory.Packages.props +26 -0
- package/framework/templates/dotnet/ai-kit/Morph.AiKit.sln +56 -0
- package/framework/templates/dotnet/ai-kit/NuGet.config +12 -0
- package/framework/templates/dotnet/ai-kit/README.md +128 -0
- package/framework/templates/dotnet/ai-kit/global.json +9 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Agents/AgentApi.cs +65 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Agents/AgentFactory.cs +289 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Agents/AgentFactoryOptions.cs +91 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Agents/AgentSpec.cs +91 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Agents/AgentSpecOptions.cs +181 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/AiKitAssemblyMarker.cs +14 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Conversation/ConversationStore.cs +174 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Conversation/IConversationStore.cs +54 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Conversation/InMemoryConversationStore.cs +75 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Evals/CountingChatClient.cs +71 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Evals/EvalAssertion.cs +246 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Evals/EvalCacheMissException.cs +57 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Evals/EvalCacheOptions.cs +78 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Evals/EvalCacheStamp.cs +225 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Evals/EvalFixture.cs +463 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Evals/EvalMode.cs +32 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Evals/EvalQualityEvaluators.cs +49 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Evals/EvalScenario.cs +214 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Evals/EvalSummary.cs +168 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Evals/OfflineChatClient.cs +142 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Evals/ShortPathResponseCache.cs +349 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/IMediaGenerator.cs +42 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/IMediaProvider.cs +77 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/MediaArtifact.cs +28 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/MediaDisclosure.cs +107 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/MediaGenerator.cs +253 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/MediaIdempotencyKey.cs +103 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/MediaJob.cs +259 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/MediaJobId.cs +21 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/MediaJobState.cs +47 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/MediaPricing.cs +102 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/MediaProvenance.cs +44 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/MediaRequest.cs +192 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/MediaResult.cs +94 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/MediaReview.cs +99 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/MediaSeams.cs +97 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/MediaStore.cs +133 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/MorphMedia.cs +93 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/Providers/GoogleImageProvider.cs +112 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/Providers/OpenAIImageProvider.cs +288 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/Providers/VeoVideoProvider.cs +158 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Middleware/IUsageCostSink.cs +29 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Middleware/UsageCostMiddleware.cs +208 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Middleware/UsageCostRecord.cs +95 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Morph.AiKit.csproj +38 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Observability/MorphOpenTelemetryExtensions.cs +119 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Observability/MorphTelemetryOptions.cs +82 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Providers/IProviderClientFactory.cs +33 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Providers/ModelAlias.cs +267 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Providers/ModelRegistry.cs +474 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Providers/model-registry.v2.json +87 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Rag/DeltaIngest.cs +169 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Rag/DeltaPlan.cs +49 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/AgentFactoryTests.cs +495 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/AgentSpecTests.cs +260 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/ConversationStoreTests.cs +405 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/DeltaIngestTests.cs +379 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Evals/EvalAssertionTests.cs +197 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Evals/EvalCacheMissTests.cs +139 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Evals/EvalCacheStampTests.cs +157 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Evals/EvalFailuresTests.cs +178 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Evals/EvalFixtureTests.cs +153 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Evals/EvalRefreshTests.cs +194 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Evals/EvalWorkspace.cs +86 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Evals/KitEvals.cs +213 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Evals/OfflineChatClientTests.cs +95 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Fakes/FakeChatClient.cs +225 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Fakes/FakeChatClientTests.cs +215 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Fakes/FakeClock.cs +33 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Fakes/FakeMediaProvider.cs +89 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Fakes/FakeProviderClientFactory.cs +55 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Fakes/FakeUsageCostSink.cs +60 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Fakes/InMemoryMediaStore.cs +131 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/MediaAccessibilityTests.cs +133 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/MediaAliasIsNotAnAgentTests.cs +127 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/MediaDisclosureTests.cs +216 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/MediaGeneratorTests.cs +264 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/MediaIdempotencyKeyTests.cs +148 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/MediaJobStateTests.cs +184 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/MediaReviewTests.cs +89 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/MediaStoreTests.cs +98 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/ModelRegistryTests.cs +451 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Morph.AiKit.Tests.csproj +76 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/SkeletonSmokeTests.cs +33 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/TelemetryTests.cs +261 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/UsageCostMiddlewareTests.cs +374 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/eval-cache/.morph-eval-cache.json +12 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/eval-cache/cache/orcamento.acme.a-resposta-estruturada/1/CF70A7CE27BBD66A/contents.data +13 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/eval-cache/cache/orcamento.acme.a-resposta-estruturada/1/CF70A7CE27BBD66A/entry.json +7 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/eval-cache/cache/triagem.acme.a-saudacao/1/19F631228C6E00BA/contents.data +13 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/eval-cache/cache/triagem.acme.a-saudacao/1/19F631228C6E00BA/entry.json +7 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/eval-cache/cache/triagem.acme.b-escalonamento/1/A24A7C9BDD8239D8/contents.data +13 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/eval-cache/cache/triagem.acme.b-escalonamento/1/A24A7C9BDD8239D8/entry.json +7 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/eval-cache/cache/triagem.globex.a-saudacao/1/E38CD37DF003EDB7/contents.data +13 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/eval-cache/cache/triagem.globex.a-saudacao/1/E38CD37DF003EDB7/entry.json +7 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/eval-datasets/orcamento/acme/a-resposta-estruturada.json +24 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/eval-datasets/triagem/acme/a-saudacao.json +23 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/eval-datasets/triagem/acme/b-escalonamento.json +24 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/eval-datasets/triagem/globex/a-saudacao.json +23 -0
- package/framework/templates/feature/decisions.md +122 -122
- package/framework/templates/frontend/nextjs/Dockerfile.nextjs.hbs +43 -43
- package/framework/templates/frontend/nextjs/client-component.tsx.hbs +26 -26
- package/framework/templates/frontend/nextjs/env.mjs.hbs +32 -32
- package/framework/templates/frontend/nextjs/feature-form.tsx.hbs +56 -56
- package/framework/templates/frontend/nextjs/page.tsx.hbs +22 -22
- package/framework/templates/frontend/nextjs/tsconfig.json.hbs +26 -26
- package/framework/templates/frontend/nextjs/use-feature.ts.hbs +54 -54
- package/framework/templates/infrastructure/docker/Dockerfile.template +58 -58
- package/framework/templates/infrastructure/docker/dockerfile-api.dockerfile +38 -38
- package/framework/templates/infrastructure/docker/dockerfile-web.dockerfile +48 -48
- package/framework/templates/infrastructure/github/README.md +56 -56
- package/framework/templates/infrastructure/github/actions/docker-build-push/action.yml.hbs +45 -45
- package/framework/templates/infrastructure/github/actions/health-check/action.yml.hbs +27 -27
- package/framework/templates/infrastructure/github/workflows/docker-build-push.yml.hbs +59 -59
- package/framework/templates/infrastructure/github/workflows/dotnet-build.yml.hbs +39 -39
- package/framework/templates/integrations/asaas-client.cs +387 -387
- package/framework/templates/integrations/asaas-webhook.cs +351 -351
- package/framework/templates/meta-prompts/fusion/fusion-agent.md +76 -76
- package/framework/templates/meta-prompts/fusion/fusion-aggregator.md +100 -100
- package/framework/templates/meta-prompts/validators/pre-commit-validator.md +95 -95
- package/framework/templates/project/validate.js +120 -120
- package/framework/templates/state.template.json +17 -17
- package/framework/templates/ui/design-system.css +226 -226
- package/package.json +3 -3
- package/src/commands/dashboard/dashboard.js +53 -53
- package/src/commands/e2e/e2e.js +15 -2
- package/src/commands/index.js +13 -13
- package/src/commands/project/checkpoint.js +209 -209
- package/src/commands/project/doctor.js +140 -5
- package/src/commands/project/update.js +469 -153
- package/src/commands/project/worktree.js +8 -1
- package/src/commands/state/advance.js +24 -2
- package/src/commands/state/approve.js +33 -1
- package/src/commands/state/create.js +72 -11
- package/src/commands/state/finish.js +333 -21
- package/src/commands/state/gate-check.js +190 -6
- package/src/commands/state/score.js +36 -1
- package/src/commands/validation/verify.js +134 -25
- package/src/core/state/phase-state-machine.js +197 -197
- package/src/core/state/state-manager.js +9 -1
- package/src/core/templates/template-renderer.js +477 -477
- package/src/dashboard/app/components/DetailPanel.jsx +11 -11
- package/src/dashboard/app/components/FlowGraph.jsx +17 -17
- package/src/dashboard/app/components/SearchFilter.jsx +22 -22
- package/src/dashboard/app/hooks/useDetailPanel.js +15 -15
- package/src/dashboard/app/main.jsx +13 -13
- package/src/dashboard/app/pages/AgentMap.jsx +370 -370
- package/src/dashboard/app/pages/PhasePipeline.jsx +408 -408
- package/src/dashboard/app/pages/RulesMap.jsx +273 -273
- package/src/dashboard/app/pages/SkillsLibrary.jsx +366 -366
- package/src/dashboard/app/pages/Standards.jsx +332 -332
- package/src/dashboard/app/styles/index.css +47 -47
- package/src/dashboard/index.html +12 -12
- package/src/dashboard/package.json +24 -24
- package/src/dashboard/scanner/phases-scanner.js +15 -15
- package/src/dashboard/scanner/rubrics-scanner.js +12 -12
- package/src/dashboard/scanner/rules-scanner.js +37 -37
- package/src/dashboard/scanner/skills-scanner.js +43 -43
- package/src/dashboard/scanner/squads-scanner.js +13 -13
- package/src/dashboard/vite-plugin-morph-data.js +17 -17
- package/src/dashboard/vite.config.js +24 -24
- package/src/lib/ai/ai-checks.js +182 -0
- package/src/lib/ai/ai-project-scan.js +347 -0
- package/src/lib/ai/code-audit.js +181 -0
- package/src/lib/ai/comment-stripper.js +184 -0
- package/src/lib/ai/pin-drift.js +138 -0
- package/src/lib/ai/registry-audit.js +285 -0
- package/src/lib/detectors/design-system-detector.js +188 -188
- package/src/lib/detectors/index.js +217 -217
- package/src/lib/e2e/compose-env.js +50 -4
- package/src/lib/evaluator-report.js +269 -15
- package/src/lib/generators/design-system-generator.js +508 -508
- package/src/lib/generators/settings-generator.js +209 -209
- package/src/lib/git/default-branch.js +92 -4
- package/src/lib/hooks/hook-executor.js +167 -167
- package/src/lib/installers/effects.js +193 -0
- package/src/lib/installers/mcp-installer.js +719 -719
- package/src/lib/installers/templates-reconcile.js +3 -3
- package/src/lib/risk-detector.js +284 -0
- package/src/lib/standards/verified-against.js +276 -0
- package/src/lib/tasks/eval-node.js +485 -0
- package/src/lib/tasks/linux-runner.js +297 -0
- package/src/lib/tasks/task-classifier.js +30 -30
- package/src/lib/tasks/task-parser.js +209 -209
- package/src/lib/tasks/test-nodes.js +486 -0
- package/src/lib/tasks/test-runner.js +410 -33
- package/src/lib/validators/checkpoint-persistence.js +39 -39
- package/src/lib/validators/css/css-validator.js +340 -340
- package/src/lib/validators/shared/emit-validator-dispatch.js +14 -14
- package/src/lib/validators/shared/issue-counter.js +14 -14
- package/src/lib/validators/verify-runner.js +583 -28
- package/src/lib/worktree/docker-audit.js +287 -0
- package/src/lib/worktree/env-allocator.js +24 -0
- package/src/lib/worktree/worktree-audit.js +30 -1
- package/src/scripts/setup-infra.js +24 -11
- package/src/utils/agent-id-mapper.js +11 -11
- package/src/utils/agents-installer.js +18 -8
- package/src/utils/claude-md-injector.js +10 -5
- package/src/utils/claude-settings-manager.js +300 -300
- package/src/utils/file-copier.js +11 -4
- package/src/utils/hooks-installer.js +29 -26
- package/src/utils/skills-installer.js +36 -29
- package/src/utils/version-checker.js +68 -3
- package/framework/standards/ai-agents/prompts-in-db.md +0 -214
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
> **Scope:** stacks=["dotnet"]
|
|
4
4
|
> **Layer:** 2 (on-keyword)
|
|
5
|
-
> **Keywords:** mcp, model context protocol, mcp client, consume mcp server, mcp tools, external tools
|
|
5
|
+
> **Keywords:** mcp, model context protocol, mcp client, consume mcp server, mcp tools, external tools, McpClient, HttpClientTransport, MRTR
|
|
6
6
|
> **Read by Claude in:** implement (quando um agente usa tools de um MCP server externo)
|
|
7
7
|
|
|
8
|
-
**Verified against:**
|
|
8
|
+
**Verified against:** ModelContextProtocol 2.2.0 + Microsoft.Agents.AI 1.20.0 + Microsoft.Extensions.AI 10.9.0 (ai-pin 2026-09-08) + revisão de spec MCP **2026-07-28**. **Verificação documental — o ai-kit não exercita MCP**, e por isso este standard NÃO carimba `provado por`. Todos os nomes de tipo abaixo foram **medidos por reflexão sobre `ModelContextProtocol.Core` 2.2.0** em 2026-09-08. Last-verified: 2026-09-08.
|
|
9
9
|
|
|
10
10
|
---
|
|
11
11
|
|
|
@@ -27,27 +27,71 @@ Casos de uso típicos:
|
|
|
27
27
|
**Package:**
|
|
28
28
|
|
|
29
29
|
```xml
|
|
30
|
-
|
|
30
|
+
<!-- no ai-pin.json -->
|
|
31
|
+
<PackageReference Include="ModelContextProtocol" Version="2.2.0" />
|
|
32
|
+
|
|
33
|
+
<!-- SÓ se o servidor expuser tools long-running. Fora do pin; apurado no nuget.org em 2026-09-08. -->
|
|
34
|
+
<PackageReference Include="ModelContextProtocol.Extensions.Tasks" Version="2.2.0" />
|
|
31
35
|
```
|
|
32
36
|
|
|
33
|
-
> O
|
|
37
|
+
> O SDK C# saiu do preview: **2.2.0**, publicado em 2026-08-13. A faixa `0.1.*` que este standard trazia é de duas majors atrás.
|
|
38
|
+
|
|
39
|
+
### Renomes da 2.x — o que não compila mais
|
|
40
|
+
|
|
41
|
+
| Nome antigo (0.1.x / 1.x) | Nome atual, **medido em 2.2.0** |
|
|
42
|
+
|---|---|
|
|
43
|
+
| `McpClientFactory.CreateAsync(transport)` | **`McpClient.CreateAsync(transport)`** — estático em `McpClient` |
|
|
44
|
+
| `SseClientTransport` | **`HttpClientTransport`** com `HttpClientTransportOptions.TransportMode = HttpTransportMode.Sse` |
|
|
45
|
+
|
|
46
|
+
`McpClientFactory` e `SseClientTransport` **não existem** em `ModelContextProtocol.Core` 2.2.0 — verificado por varredura dos tipos exportados. Não são alternativas; são nomes mortos.
|
|
34
47
|
|
|
35
48
|
**Fluxo de consumo:**
|
|
36
49
|
|
|
37
|
-
1. `
|
|
50
|
+
1. `McpClient.CreateAsync(transport)` — conecta ao MCP server e devolve um client descartável
|
|
38
51
|
2. `mcpClient.ListToolsAsync()` — descobre as tools disponíveis no servidor
|
|
39
|
-
3.
|
|
40
|
-
|
|
52
|
+
3. Passa as tools ao agente via `AsAIAgent(..., tools: [.. mcpTools])`
|
|
53
|
+
|
|
54
|
+
**`McpClientTool` herda de `AIFunction`.** Medido: `ModelContextProtocol.Client.McpClientTool : Microsoft.Extensions.AI.AIFunction`, e `AIFunction` é um `AITool`. Ou seja, **o `.Cast<AITool>()` é desnecessário** em qualquer ponto que aceite `IEnumerable<AITool>` — a conversão é implícita por herança. Mantenha o cast apenas quando precisar de um `AITool[]` a partir de um `Concat` de coleções de tipos diferentes.
|
|
41
55
|
|
|
42
|
-
**Transports suportados:**
|
|
56
|
+
**Transports suportados (medidos):**
|
|
43
57
|
|
|
44
|
-
| Transport | Classe | Quando usar |
|
|
45
|
-
|
|
46
|
-
| stdio | `StdioClientTransport` | MCP server local (processo filho — `npx`, executável) |
|
|
47
|
-
| HTTP (
|
|
58
|
+
| Transport | Classe | Opções | Quando usar |
|
|
59
|
+
|-----------|--------|--------|------------|
|
|
60
|
+
| stdio | `StdioClientTransport` | `StdioClientTransportOptions`: `Name`, `Command`, `Arguments`, `WorkingDirectory`, `EnvironmentVariables`, `ShutdownTimeout` | MCP server local (processo filho — `npx`, executável) |
|
|
61
|
+
| Streamable HTTP | `HttpClientTransport` | `HttpClientTransportOptions`: `Endpoint`, `TransportMode` (`AutoDetect` \| `StreamableHttp` \| `Sse`), `AdditionalHeaders`, `OAuth`, `ConnectionTimeout` | MCP server remoto |
|
|
62
|
+
|
|
63
|
+
`HttpTransportMode.Sse` existe para falar com servidores da era HTTP+SSE, que a revisão `2026-07-28` marcou como **Deprecated**. Para servidor novo, `StreamableHttp` (ou `AutoDetect`).
|
|
48
64
|
|
|
49
65
|
**Regra importante:** use `await using` no `mcpClient` — o dispose fecha o transporte corretamente.
|
|
50
66
|
|
|
67
|
+
### Modo stateless quebra três métodos
|
|
68
|
+
|
|
69
|
+
A revisão `2026-07-28` removeu as sessões, e o servidor C# 2.2.0 nasce **stateless por default**. Consequência para quem escreve **cliente**: `ElicitAsync`, `SampleAsync` e `RequestRootsAsync` dependem de uma sessão persistente e de requests server→client, e **falham** contra um servidor stateless. Sampling e Roots estão, além disso, **deprecados** pela SEP-2577 — o próprio `McpServerOptions.MaxSamplingOutputTokens` carrega essa frase no `[Obsolete]`.
|
|
70
|
+
|
|
71
|
+
A via que funciona nas duas configurações é o **MRTR** (*More-Round-Trip Response*), medido em `ModelContextProtocol.Protocol`:
|
|
72
|
+
|
|
73
|
+
```csharp
|
|
74
|
+
// No SERVIDOR: em vez de chamar de volta o cliente, devolva o pedido de input.
|
|
75
|
+
throw new InputRequiredException(new InputRequiredResult
|
|
76
|
+
{
|
|
77
|
+
RequestState = state,
|
|
78
|
+
InputRequests = { ["confirm"] = InputRequest.ForElicitation(elicitParams) },
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
// No CLIENTE: responda os pedidos e siga.
|
|
82
|
+
await mcpClient.ResolveInputRequestsAsync(answers, ct);
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
`InputRequest` tem as três fábricas `ForElicitation`, `ForSampling` e `ForRootsList`.
|
|
86
|
+
|
|
87
|
+
### Tasks (long-running) mudaram de pacote E de wire
|
|
88
|
+
|
|
89
|
+
Long-running saiu do core para **`ModelContextProtocol.Extensions.Tasks`** (2.2.0, apurado em 2026-09-08). **Não há compatibilidade de wire** com a implementação experimental das 1.3/1.4: quem usava aquilo **migra**, não apenas sobe a versão. Sinal de que é preciso migrar: código que fala tasks e continua compilando depois do upgrade — o formato mudou no fio, não na API.
|
|
90
|
+
|
|
91
|
+
### Custo de definição de tool por turno
|
|
92
|
+
|
|
93
|
+
Toda tool descoberta entra na **definição** enviada ao modelo a cada turno — nome, descrição e JSON Schema dos parâmetros. Um servidor MCP com 60 tools cobra isso em todo request, mesmo nos turnos em que nenhuma é chamada. Pode-se podar com `mcpClient.RemoveKnownTools([...])` / `AddKnownTools([...])`, ou registrando só o recorte relevante no agente. O critério de quantas tools cabem num agente é de `ai-agents-sweet-spot` — não é duplicado aqui.
|
|
94
|
+
|
|
51
95
|
---
|
|
52
96
|
|
|
53
97
|
## Exemplo C#
|
|
@@ -61,7 +105,7 @@ using Microsoft.Agents.AI;
|
|
|
61
105
|
using Microsoft.Extensions.AI;
|
|
62
106
|
|
|
63
107
|
// 1. Conectar ao MCP server (GitHub via npx)
|
|
64
|
-
await using var mcpClient = await
|
|
108
|
+
await using var mcpClient = await McpClient.CreateAsync(
|
|
65
109
|
new StdioClientTransport(new()
|
|
66
110
|
{
|
|
67
111
|
Name = "GitHubServer",
|
|
@@ -70,14 +114,15 @@ await using var mcpClient = await McpClientFactory.CreateAsync(
|
|
|
70
114
|
}));
|
|
71
115
|
|
|
72
116
|
// 2. Descobrir as tools do servidor
|
|
73
|
-
|
|
117
|
+
IList<McpClientTool> mcpTools = await mcpClient.ListToolsAsync();
|
|
74
118
|
|
|
75
119
|
// 3. Criar o agente MAF com as MCP tools registradas
|
|
76
|
-
//
|
|
120
|
+
// McpClientTool herda de AIFunction (que é AITool) — sem cast.
|
|
121
|
+
// _modelRegistry vem de ModelRegistry (ai-agents-providers-model-registry)
|
|
77
122
|
AIAgent agent = _modelRegistry.GetChatClient("text-default")
|
|
78
123
|
.AsAIAgent(
|
|
79
124
|
instructions: "You answer questions about GitHub repositories.",
|
|
80
|
-
tools: [.. mcpTools
|
|
125
|
+
tools: [.. mcpTools]);
|
|
81
126
|
|
|
82
127
|
// 4. Usar o agente normalmente
|
|
83
128
|
var response = await agent.RunAsync(
|
|
@@ -85,16 +130,17 @@ var response = await agent.RunAsync(
|
|
|
85
130
|
Console.WriteLine(response.Text);
|
|
86
131
|
```
|
|
87
132
|
|
|
88
|
-
**Variante com MCP server remoto (HTTP
|
|
133
|
+
**Variante com MCP server remoto (Streamable HTTP):**
|
|
89
134
|
|
|
90
135
|
```csharp
|
|
91
136
|
using ModelContextProtocol.Client;
|
|
92
137
|
|
|
93
|
-
await using var mcpClient = await
|
|
94
|
-
new
|
|
138
|
+
await using var mcpClient = await McpClient.CreateAsync(
|
|
139
|
+
new HttpClientTransport(new HttpClientTransportOptions
|
|
95
140
|
{
|
|
96
141
|
Name = "RemoteToolsServer",
|
|
97
|
-
|
|
142
|
+
Endpoint = new Uri("https://tools.example.com/mcp"),
|
|
143
|
+
TransportMode = HttpTransportMode.StreamableHttp, // .Sse só para servidor legado
|
|
98
144
|
}));
|
|
99
145
|
|
|
100
146
|
var mcpTools = await mcpClient.ListToolsAsync();
|
|
@@ -105,7 +151,7 @@ var mcpTools = await mcpClient.ListToolsAsync();
|
|
|
105
151
|
|
|
106
152
|
```csharp
|
|
107
153
|
// Conectar a dois servidores e combinar as tools
|
|
108
|
-
await using var githubClient = await
|
|
154
|
+
await using var githubClient = await McpClient.CreateAsync(
|
|
109
155
|
new StdioClientTransport(new()
|
|
110
156
|
{
|
|
111
157
|
Name = "GitHub",
|
|
@@ -113,7 +159,7 @@ await using var githubClient = await McpClientFactory.CreateAsync(
|
|
|
113
159
|
Arguments = ["-y", "@modelcontextprotocol/server-github"],
|
|
114
160
|
}));
|
|
115
161
|
|
|
116
|
-
await using var fsClient = await
|
|
162
|
+
await using var fsClient = await McpClient.CreateAsync(
|
|
117
163
|
new StdioClientTransport(new()
|
|
118
164
|
{
|
|
119
165
|
Name = "Filesystem",
|
|
@@ -121,10 +167,10 @@ await using var fsClient = await McpClientFactory.CreateAsync(
|
|
|
121
167
|
Arguments = ["-y", "@modelcontextprotocol/server-filesystem", "/repo"],
|
|
122
168
|
}));
|
|
123
169
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
.
|
|
127
|
-
|
|
170
|
+
AITool[] allTools = [
|
|
171
|
+
.. await githubClient.ListToolsAsync(),
|
|
172
|
+
.. await fsClient.ListToolsAsync(),
|
|
173
|
+
]; // McpClientTool : AIFunction : AITool — a conversão é por herança
|
|
128
174
|
|
|
129
175
|
AIAgent agent = _modelRegistry.GetChatClient("text-default")
|
|
130
176
|
.AsAIAgent(
|
|
@@ -164,7 +210,11 @@ AIAgent agent = _modelRegistry.GetChatClient("text-default")
|
|
|
164
210
|
|-------------|---------|---------|
|
|
165
211
|
| Criar um MCP server próprio só para o agente do mesmo projeto chamar | Overhead desnecessário de protocolo e deploy | Escrever tool nativa com `[Description]` + `AIFunctionFactory.Create()` |
|
|
166
212
|
| Não tratar indisponibilidade do MCP server | O MCP server pode estar offline ou lento; o agente quebra | Usar `ResilientToolMiddleware` para capturar `HttpRequestException` e `TimeoutException` (ver `ai-agents-production`) |
|
|
167
|
-
| Não usar `await using` no `mcpClient` | Processo filho (npx) fica zumbi; leak de recursos | Sempre `await using var mcpClient = await
|
|
213
|
+
| Não usar `await using` no `mcpClient` | Processo filho (npx) fica zumbi; leak de recursos | Sempre `await using var mcpClient = await McpClient.CreateAsync(...)` |
|
|
214
|
+
| Usar `McpClientFactory` ou `SseClientTransport` | Não existem na 2.x — o código não compila | `McpClient.CreateAsync` e `HttpClientTransport` |
|
|
215
|
+
| Contar com `ElicitAsync` / `SampleAsync` / `RequestRootsAsync` | Exigem sessão persistente; o servidor 2.2.0 é stateless por default, e Sampling/Roots estão deprecados (SEP-2577) | MRTR: `InputRequiredException` + `InputRequest.ForElicitation(...)` |
|
|
216
|
+
| Só subir a versão do pacote de Tasks vindo das 1.3/1.4 | Não há compatibilidade de **wire**; compila e falha no fio | Migrar para `ModelContextProtocol.Extensions.Tasks` conscientemente |
|
|
217
|
+
| Registrar as 60 tools de um servidor "porque estavam lá" | A definição de toda tool é reenviada a cada turno | Podar (`RemoveKnownTools`) ou registrar só o recorte; critério em `ai-agents-sweet-spot` |
|
|
168
218
|
| Hardcodar o model diretamente (`new ChatClient("gpt-4o", key)`) | Viola provider-agnostic; difícil de trocar | Sempre `_modelRegistry.GetChatClient("alias")` (ver `ai-agents-providers-model-registry`) |
|
|
169
219
|
|
|
170
220
|
|
|
@@ -172,11 +222,12 @@ AIAgent agent = _modelRegistry.GetChatClient("text-default")
|
|
|
172
222
|
|
|
173
223
|
## Checklist (verifiable by morph-eval)
|
|
174
224
|
|
|
175
|
-
- [ ] `ModelContextProtocol` presente no `.csproj`
|
|
225
|
+
- [ ] `ModelContextProtocol` presente no `.csproj` com versão exata (2.2.0 no pin) — sem faixa flutuante
|
|
176
226
|
- [ ] `await using var mcpClient` — dispose correto do transporte
|
|
177
|
-
- [ ] `
|
|
227
|
+
- [ ] `McpClient.CreateAsync(...)` — nenhuma ocorrência de `McpClientFactory` ou `SseClientTransport`
|
|
178
228
|
- [ ] `ListToolsAsync()` chamado antes de criar o agente
|
|
179
|
-
- [ ]
|
|
229
|
+
- [ ] Nenhum `.Cast<AITool>()` supérfluo (`McpClientTool` já é `AIFunction`)
|
|
230
|
+
- [ ] Nenhum `ElicitAsync`/`SampleAsync`/`RequestRootsAsync` contra servidor stateless
|
|
180
231
|
- [ ] Agente criado via `_modelRegistry.GetChatClient("alias").AsAIAgent(...)` — provider-agnostic
|
|
181
232
|
- [ ] `ResilientToolMiddleware` ou equivalente registrado (o MCP server pode ficar indisponível)
|
|
182
233
|
- [ ] Nenhum `Guid.NewGuid()` — usar `Guid.CreateVersion7()` se IDs são necessários
|
|
@@ -189,9 +240,11 @@ AIAgent agent = _modelRegistry.GetChatClient("text-default")
|
|
|
189
240
|
- `ai-agents-production` — panorama de MCP Integration, `ResilientToolMiddleware`, middleware pipeline
|
|
190
241
|
- `ai-agents-mcp-server` — expor capacidades do próprio projeto como MCP server
|
|
191
242
|
- `integration/mcp/mcp-tools.md` — MCPs no workflow do morph-spec (Playwright, Context7, Neon) — contexto complementar, escopo diferente
|
|
192
|
-
- [ModelContextProtocol C# SDK](https://github.com/modelcontextprotocol/csharp-sdk)
|
|
243
|
+
- [ModelContextProtocol C# SDK](https://github.com/modelcontextprotocol/csharp-sdk) — `docs/concepts/**` (lido 2026-09-08)
|
|
244
|
+
- [MCP — versionamento da especificação](https://modelcontextprotocol.io/specification/versioning) — revisão corrente `2026-07-28` (lido 2026-09-08)
|
|
245
|
+
- [NuGet — ModelContextProtocol 2.2.0](https://www.nuget.org/packages/ModelContextProtocol/2.2.0) (publicado 2026-08-13)
|
|
193
246
|
- [Using MCP Tools — MAF docs](https://learn.microsoft.com/agent-framework/user-guide/model-context-protocol/using-mcp-tools)
|
|
194
247
|
|
|
195
248
|
---
|
|
196
249
|
|
|
197
|
-
*MORPH-SPEC by Polymorphism Tech — ai-agents/mcp-tools.md
|
|
250
|
+
*MORPH-SPEC by Polymorphism Tech — ai-agents/mcp-tools.md v2.0 (2026-09-08)*
|
|
@@ -0,0 +1,352 @@
|
|
|
1
|
+
# Media Pipeline — job, revisão humana, proveniência e marcação
|
|
2
|
+
|
|
3
|
+
> **Scope:** stacks=["dotnet"]
|
|
4
|
+
> **Layer:** 1 (load when relevant)
|
|
5
|
+
> **Keywords:** media pipeline, media job, geração de mídia, revisão humana, C2PA, SynthID, AI Act, idempotência de mídia, teto de custo, marcação de IA
|
|
6
|
+
> **Read by Claude in:** plan e implement (sempre que a feature gerar imagem ou vídeo)
|
|
7
|
+
|
|
8
|
+
**Verified against:** Microsoft.Extensions.AI 10.9.0 + OpenAI 2.13.0 + Google.GenAI 1.21.0 (ai-pin 2026-09-08); provado por `templates/dotnet/ai-kit/src/Morph.AiKit/Media/` — a máquina de estados (`MediaJob`), a revisão humana (`MediaReview`), a marcação exigida na publicação (`MediaDisclosure` + `MediaJob.Publish`), as duas chaves (`MediaIdempotencyKey` × `MediaHash`), o storage por conteúdo (`MediaStore`) e a acessibilidade `internal` de `IMediaProvider` compilam e são exercitados por teste. Preço, data de desligamento, C2PA/SynthID e o texto legal do AI Act são **verificação documental** contra as páginas de §Como re-verificar este standard. Last-verified: 2026-09-08.
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
**Fronteira, primeiro.** `ai-agents/durable-workflows-hitl.md` cobre HITL e checkpoint **dentro de
|
|
13
|
+
um Workflow MAF** — `RequestPort`, `RequestInfoEvent`, `ICheckpointStore`. Este standard é a outra
|
|
14
|
+
coisa: um **pipeline de domínio**, cujo mecanismo de job é `BackgroundService`/Channels ou
|
|
15
|
+
Hangfire/Quartz com storage persistido. O wiring de job (enqueue, retry, `IDbContextFactory`,
|
|
16
|
+
dashboard) já é standard e **não se repete aqui**:
|
|
17
|
+
`backend/integrations/hangfire/hangfire-jobs.md`. Use `RequestPort` só quando o passo humano é, de
|
|
18
|
+
fato, um nó de um grafo de agente — o que quase nunca é o caso de aprovar uma foto de catálogo.
|
|
19
|
+
|
|
20
|
+
O que este standard acrescenta ao mecanismo de job é o que o job **não sabe**: quais estados
|
|
21
|
+
existem, quem pode aprovar, o que é persistido, o que é marcado e quanto pode custar.
|
|
22
|
+
|
|
23
|
+
Imagem: `ai-agents/modalities-image-gen.md`. Vídeo: `ai-agents/media-video.md`.
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## A regra dura
|
|
28
|
+
|
|
29
|
+
> **Nunca gere mídia dentro de um turno de conversa.** Nem em WhatsApp, nem em chat, nem em webhook
|
|
30
|
+
> síncrono. O turno **enfileira e confirma**; a mídia volta depois, revisada.
|
|
31
|
+
|
|
32
|
+
Três números sustentam a regra, e nenhum deles é opinião:
|
|
33
|
+
|
|
34
|
+
| Fato | Consequência dentro do turno |
|
|
35
|
+
|---|---|
|
|
36
|
+
| Imagem: latência documentada de **até 2 minutos** para prompt complexo | O turno estoura antes da resposta |
|
|
37
|
+
| Vídeo: **11 s a 6 min**, assíncrono por desenho em todo provedor | Não existe caminho síncrono para tentar |
|
|
38
|
+
| Custo **por chamada**, sem teto natural | Um usuário curioso vira uma fatura |
|
|
39
|
+
| **Zero revisão possível** dentro do turno | Claim visual errado sai direto para o cliente |
|
|
40
|
+
|
|
41
|
+
O quarto é o que não tem contorno técnico. Latência se resolve com paciência e custo com orçamento;
|
|
42
|
+
"ninguém olhou antes de publicar" não se resolve com nada.
|
|
43
|
+
|
|
44
|
+
> **De onde vêm os dois números de latência.** "Até 2 minutos" é a frase do guia de geração de imagem
|
|
45
|
+
> da OpenAI (`https://developers.openai.com/api/docs/guides/image-generation`); "11 s a 6 min" é a
|
|
46
|
+
> faixa da documentação do Veo (`https://ai.google.dev/gemini-api/docs/veo`). Ambas consultadas em
|
|
47
|
+
> **2026-09-07**, e ambas na lista de §Como re-verificar este standard. **Nenhum dos dois foi medido
|
|
48
|
+
> por esta casa** — gerar mídia para cronometrar custaria dinheiro, e um número medido uma vez numa
|
|
49
|
+
> região não vale como SLA.
|
|
50
|
+
|
|
51
|
+
### Como a regra é presa
|
|
52
|
+
|
|
53
|
+
**Prosa não prende regra.** O que prende é a forma da API:
|
|
54
|
+
|
|
55
|
+
- O tipo que **produz bytes** (`IMediaProvider` e as implementações de provedor) é `internal` ao
|
|
56
|
+
assembly do kit, com `InternalsVisibleTo` liberando apenas os testes. Um handler de mensagem no
|
|
57
|
+
projeto consumidor **não consegue nomear** esse tipo — o código não compila.
|
|
58
|
+
- A única superfície pública é `IMediaGenerator.EnqueueAsync`, que devolve um **id de job** e nunca
|
|
59
|
+
bytes. `GetAsync` devolve o job, com o estado dele.
|
|
60
|
+
- O worker que chama o provedor também é `internal`. Ele é montado por uma **raiz de composição**
|
|
61
|
+
(`MorphMedia.Create(options)`, no exemplar), que devolve as duas interfaces públicas —
|
|
62
|
+
`IMediaGenerator` e `IMediaJobRunner` — e nenhuma forma de alcançar o provider. O projeto registra
|
|
63
|
+
o resultado no seu contêiner numa linha; a montagem **não** é uma extensão de `IServiceCollection`,
|
|
64
|
+
porque isso obrigaria o kit a referenciar o pacote de DI, e o exemplar deste repositório escreve o
|
|
65
|
+
porquê no próprio arquivo. A propriedade que importa é a mesma nos dois desenhos: **não existe
|
|
66
|
+
caminho público até o tipo que produz bytes.**
|
|
67
|
+
|
|
68
|
+
É a diferença entre "o standard diz para não fazer" e "o compilador recusa". O exemplar está em
|
|
69
|
+
`templates/dotnet/ai-kit/src/Morph.AiKit/Media/`, e a acessibilidade é asserida por reflexão num
|
|
70
|
+
teste — porque uma regra que ninguém viu falhar pode ser a regra errada.
|
|
71
|
+
|
|
72
|
+
### O que o tipo prende, e o que ele não prende
|
|
73
|
+
|
|
74
|
+
Ser exato aqui vale mais que ser tranquilizador, porque é o exato que sobrevive a uma revisão.
|
|
75
|
+
|
|
76
|
+
**Prende:** um handler não consegue **obter bytes** (a superfície pública devolve id de job) nem
|
|
77
|
+
**nomear** o tipo que os produz (`internal` — o código não compila). Nenhuma quantidade de pressa
|
|
78
|
+
contorna isso, e a acessibilidade é asserida por reflexão num teste.
|
|
79
|
+
|
|
80
|
+
**Não prende:** `IMediaJobRunner.RunAsync` é **público** — precisa ser, porque é o
|
|
81
|
+
`BackgroundService`/Hangfire do projeto que o dispara. Um handler pode escrever
|
|
82
|
+
`await runner.RunAsync(id)` e, com isso, **aguardar a chamada paga dentro do turno**. Ele não vê os
|
|
83
|
+
bytes, mas paga a latência: os mesmos até 2 min em imagem, 11 s a 6 min em vídeo.
|
|
84
|
+
|
|
85
|
+
Ou seja: o tipo fecha **"gere estes bytes agora"** e deixa aberto **"rode este job agora"**. Fechar
|
|
86
|
+
o segundo também exigiria esconder o gatilho de quem precisa dele, e o remédio seria pior. A leitura
|
|
87
|
+
no seu projeto é literal: **um `await` num runner dentro de um handler de mensagem é o defeito**,
|
|
88
|
+
mesmo compilando — e é isso que a revisão de código procura, porque o compilador não vai procurar
|
|
89
|
+
por ela.
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
## A máquina de estados
|
|
94
|
+
|
|
95
|
+
```
|
|
96
|
+
Pending ──▶ Generating ──▶ Generated ──┬──▶ Approved ──▶ Published
|
|
97
|
+
│ │ ├──▶ Rejected
|
|
98
|
+
└────────────┴──▶ Failed └──▶ RejectedByPolicy
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
| Estado | Significa | Retryable? |
|
|
102
|
+
|---|---|---|
|
|
103
|
+
| `Pending` | Pedido aceito, nada gasto ainda | — |
|
|
104
|
+
| `Generating` | Chamada paga em voo (ou tarefa remota em polling) | — |
|
|
105
|
+
| `Generated` | Bytes existem no **seu** storage | — |
|
|
106
|
+
| `Approved` | Humano aprovou. **Única** porta para `Published` | — |
|
|
107
|
+
| `Rejected` | Humano recusou | não |
|
|
108
|
+
| `RejectedByPolicy` | **Bloqueio de moderação do provedor** | **não** |
|
|
109
|
+
| `Published` | Publicado, com a marcação **registrada junto** — ver a terceira porta abaixo | — |
|
|
110
|
+
| `Failed` | Erro técnico (429, 5xx, timeout, download quebrado) | **sim** |
|
|
111
|
+
|
|
112
|
+
**`RejectedByPolicy` não é `Failed`, e a distinção é dinheiro.** Um bloqueio de moderação é uma
|
|
113
|
+
resposta definitiva: retentá-lo gasta para receber o mesmo "não" — e nos provedores que cobram o
|
|
114
|
+
bloqueio, gasta duas vezes. Modelar bloqueio como erro técnico é como um retry loop vira uma fatura.
|
|
115
|
+
|
|
116
|
+
**`Approve(reviewer)` é a única transição para `Approved`**, e `Publish()` devolve falha a partir de
|
|
117
|
+
qualquer estado que não seja `Approved`. É assim que "há revisão humana" deixa de ser uma frase no
|
|
118
|
+
README e vira um caminho que o código não tem.
|
|
119
|
+
|
|
120
|
+
**A publicação tem três portas, e não uma.** No exemplar, a assinatura é
|
|
121
|
+
`Publish(MediaDisclosure? disclosure, DateTimeOffset publishedAt)`, e ela recusa:
|
|
122
|
+
|
|
123
|
+
1. **estado** diferente de `Approved` — inclusive `Generated`, que é o atalho que alguém sempre quer;
|
|
124
|
+
2. **finalidade não publicável** — `Draft` se declarava "nunca publicável" num comentário que nada
|
|
125
|
+
cobrava;
|
|
126
|
+
3. **marcação ausente** quando a finalidade a exige (`RequiresDisclosure()`: catálogo e marketing).
|
|
127
|
+
|
|
128
|
+
A ordem importa e é testada: um job não aprovado reclama da revisão humana, **não** da marcação —
|
|
129
|
+
mandar consertar o rótulo de algo que ninguém revisou manda consertar a coisa errada.
|
|
130
|
+
|
|
131
|
+
---
|
|
132
|
+
|
|
133
|
+
## As duas chaves de idempotência
|
|
134
|
+
|
|
135
|
+
Duas chaves distintas, e confundi-las é o defeito caro:
|
|
136
|
+
|
|
137
|
+
| Chave | Fórmula | O que dedupe |
|
|
138
|
+
|---|---|---|
|
|
139
|
+
| **De pedido** | `sha256(provider + model + prompt normalizado + sha256 de cada referência + opções)` | A **chamada paga** |
|
|
140
|
+
| **De conteúdo** | `sha256(bytes)` | O **storage** |
|
|
141
|
+
|
|
142
|
+
A chave **de pedido** é consultada **antes** de chamar o provedor: se já existe job com a mesma
|
|
143
|
+
chave e resultado, reuse o artefato em vez de pagar de novo. É o que faz um retry — de fila, de
|
|
144
|
+
worker reiniciado, de webhook duplicado — custar zero.
|
|
145
|
+
|
|
146
|
+
A chave **de conteúdo** é o endereço do arquivo: `PutAsync` do mesmo conteúdo devolve o caminho já
|
|
147
|
+
existente sem regravar. Dois pedidos diferentes podem produzir bytes idênticos; um pedido só sempre
|
|
148
|
+
produz o mesmo pedido.
|
|
149
|
+
|
|
150
|
+
Trocar a foto de referência muda a chave de pedido mesmo com prompt idêntico — por isso o sha256 de
|
|
151
|
+
**cada** referência entra na fórmula, e não a contagem delas.
|
|
152
|
+
|
|
153
|
+
---
|
|
154
|
+
|
|
155
|
+
## Storage
|
|
156
|
+
|
|
157
|
+
- **Bytes no blob próprio**, sempre. URL de provedor expira: o Veo apaga o arquivo em 2 dias, e todo
|
|
158
|
+
agregador devolve URL temporária.
|
|
159
|
+
- O banco guarda **caminho relativo + sha256**, nunca URL absoluta de provedor e nunca o caminho
|
|
160
|
+
absoluto do disco de hoje.
|
|
161
|
+
- O download acontece **no mesmo passo** que detectou a conclusão, antes de marcar `Generated`. Um
|
|
162
|
+
job em `Generated` sem bytes no seu storage está mentindo sobre o próprio estado.
|
|
163
|
+
|
|
164
|
+
---
|
|
165
|
+
|
|
166
|
+
## Proveniência persistida
|
|
167
|
+
|
|
168
|
+
Um registro por job, gravado no momento da geração:
|
|
169
|
+
|
|
170
|
+
| Campo | Por quê |
|
|
171
|
+
|---|---|
|
|
172
|
+
| `provider`, `modelId` | Sem eles, nenhuma auditoria de "que modelo gerou isto" é possível |
|
|
173
|
+
| `promptFinal` | O texto que foi enviado, não o template |
|
|
174
|
+
| `revisedPrompt` | O que o provedor reescreveu — frequentemente diferente do enviado |
|
|
175
|
+
| `refsHash` | sha256 das referências, o mesmo que entra na chave de pedido |
|
|
176
|
+
| `options` | Tamanho, qualidade, formato, background |
|
|
177
|
+
| `responseId` | O id do lado do provedor, para abrir chamado |
|
|
178
|
+
| `estimatedCostUsd` | Gravado **antes** da chamada — ver §Teto de custo |
|
|
179
|
+
| `createdAt` | — |
|
|
180
|
+
| `c2paPreserved` | Se os metadados sobreviveram ao seu pipeline |
|
|
181
|
+
|
|
182
|
+
**Metadados C2PA são preservados: nada de re-encode destrutivo.** Um resize ou uma recompressão
|
|
183
|
+
"para economizar CDN" apaga a credencial de conteúdo que o provedor embutiu, e você fica sem a única
|
|
184
|
+
prova técnica de origem que tinha.
|
|
185
|
+
|
|
186
|
+
---
|
|
187
|
+
|
|
188
|
+
## Marcação, C2PA e SynthID
|
|
189
|
+
|
|
190
|
+
As imagens das duas famílias já vêm com credencial embutida — **C2PA Content Credentials + SynthID**
|
|
191
|
+
na OpenAI, **SynthID** em toda imagem Gemini — e a OpenAI expõe um endpoint
|
|
192
|
+
`content_provenance_check` que verifica ambos.
|
|
193
|
+
|
|
194
|
+
**E isso não basta**, por três razões escritas na própria documentação:
|
|
195
|
+
|
|
196
|
+
1. **C2PA cai com screenshot e com re-encode.** Qualquer trânsito por uma ferramenta que reprocessa
|
|
197
|
+
o arquivo apaga a credencial. SynthID sobrevive melhor, mas não é infalível.
|
|
198
|
+
2. **`not_detected` não significa "feito por humano".** A ausência de marca é ausência de
|
|
199
|
+
informação, nunca prova de origem.
|
|
200
|
+
3. **A credencial é invisível para quem olha a imagem.** Um cliente no WhatsApp não roda verificador
|
|
201
|
+
de proveniência.
|
|
202
|
+
|
|
203
|
+
Por isso **a marcação visível é obrigação separada**, aplicada no ponto de publicação e não no de
|
|
204
|
+
geração.
|
|
205
|
+
|
|
206
|
+
### Como esta obrigação é presa — e até onde ela chega
|
|
207
|
+
|
|
208
|
+
Uma obrigação legal escrita só em prosa é a mesma coisa que nenhuma obrigação: alguém esquece, o
|
|
209
|
+
teste fica verde, e o silêncio vira aprovação. No exemplar ela é **um parâmetro obrigatório da
|
|
210
|
+
transição**, não um lembrete:
|
|
211
|
+
|
|
212
|
+
```csharp
|
|
213
|
+
public sealed record MediaDisclosure(string Text, string Surface, DateTimeOffset AppliedAt);
|
|
214
|
+
|
|
215
|
+
// Texto E superfície são exigidos na construção: "marcado" sem dizer ONDE não responde
|
|
216
|
+
// se alguém consegue ver, e texto em branco é o campo preenchido "para passar".
|
|
217
|
+
public static bool RequiresDisclosure(this MediaPurpose purpose)
|
|
218
|
+
=> purpose is MediaPurpose.CatalogPhoto or MediaPurpose.Marketing;
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
`MediaJob.Publish(null, at)` sobre um job de catálogo **aprovado** devolve falha nomeando a
|
|
222
|
+
marcação. A mutação foi rodada: removida a terceira porta, os dois casos de
|
|
223
|
+
`MediaDisclosureTests.PublishFailsWithoutADisclosureWhenThePurposeDemandsOne` morrem
|
|
224
|
+
(`CatalogPhoto` e `Marketing`), a suíte cai de 220/0 para 220/2, e a mensagem de falha diz por quê.
|
|
225
|
+
|
|
226
|
+
**O limite, dito em voz alta.** Isto prova que a **decisão foi tomada e gravada**, com texto e
|
|
227
|
+
superfície nomeados — não que o rótulo chegou aos olhos de alguém. Nenhum tipo em C# alcança um
|
|
228
|
+
pixel: a renderização é do aplicativo consumidor. O que o mecanismo elimina é o caminho silencioso
|
|
229
|
+
"esquecemos de marcar", que passa a ser uma recusa na publicação.
|
|
230
|
+
|
|
231
|
+
### EU AI Act art. 50
|
|
232
|
+
|
|
233
|
+
O Regulamento (UE) 2024/1689 exige, no art. 50, transparência sobre conteúdo sintético: imagem
|
|
234
|
+
gerada que **possa parecer autêntica** sobre produto, pessoa ou lugar exige aviso claro no primeiro
|
|
235
|
+
contato.
|
|
236
|
+
|
|
237
|
+
**Ressalva de fonte, declarada em vez de escondida.** O art. 113 do regulamento diz *"It shall apply
|
|
238
|
+
from 2 August 2026"*, e o Capítulo IV — onde vive o art. 50 — **não tem data própria** naquele
|
|
239
|
+
artigo; daí a leitura de que ele segue a data geral de **2026-08-02**. Essa derivação é **leitura do
|
|
240
|
+
artigo, não citação de um considerando explícito**, e foi feita sobre
|
|
241
|
+
`https://artificialintelligenceact.eu/article/113/`, uma fonte secundária que reproduz o texto.
|
|
242
|
+
**Antes de o seu projeto assumir consequência jurídica** — prazo, multa, obrigação de rótulo —
|
|
243
|
+
confira o mesmo artigo no EUR-Lex e registre a leitura com a data. Este standard afirma o
|
|
244
|
+
mecanismo (marcar é obrigação de desenho); ele **não** é parecer jurídico, e escrever um número de
|
|
245
|
+
multa aqui como se fosse fato verificado seria exatamente o defeito que ele combate.
|
|
246
|
+
|
|
247
|
+
Regra de desenho, independente do prazo: **produto real sobre cena gerada é declarado como tal**, e
|
|
248
|
+
nenhuma geração cria claim visual de material, medida ou cor que o produto não tem. Isso é
|
|
249
|
+
codificado — uma lista de atributos bloqueados no validador do prompt — e não confiado ao texto do
|
|
250
|
+
prompt.
|
|
251
|
+
|
|
252
|
+
---
|
|
253
|
+
|
|
254
|
+
## Revisão humana
|
|
255
|
+
|
|
256
|
+
- `Approved` **exige humano** antes de `Published` para qualquer mídia de catálogo ou peça pública.
|
|
257
|
+
- O revisor é identificado e carimbado com data no `MediaReview` — "aprovado" sem quem e sem quando
|
|
258
|
+
não é revisão, é campo booleano.
|
|
259
|
+
- **Juiz LLM é pré-filtro, nunca substituto.** Ele derruba as candidatas obviamente ruins e economiza
|
|
260
|
+
o tempo do humano; ele não assume a responsabilidade de um claim visual.
|
|
261
|
+
- O gate humano natural é a **escolha entre N candidatas** geradas em qualidade baixa. A escada de
|
|
262
|
+
custo e a revisão são o mesmo passo, não dois.
|
|
263
|
+
|
|
264
|
+
---
|
|
265
|
+
|
|
266
|
+
## Teto de custo
|
|
267
|
+
|
|
268
|
+
- **Orçamento por tenant/dia em unidades**, não em reais: imagens × qualidade para imagem, segundos
|
|
269
|
+
de saída para vídeo. Unidade é o que o provedor cobra; moeda é derivada.
|
|
270
|
+
- **`estimatedCostUsd` é gravado antes da chamada**, com a tarifa da tabela de preço do standard da
|
|
271
|
+
modalidade (`modalities-image-gen.md` §Custo por chamada, `media-video.md` §Custo por segundo).
|
|
272
|
+
Estimar depois é contabilidade; estimar antes é controle.
|
|
273
|
+
- Estouro de teto é recusa **no enqueue**, com erro nomeado — nunca uma chamada que já saiu e um
|
|
274
|
+
alerta que chega depois.
|
|
275
|
+
|
|
276
|
+
---
|
|
277
|
+
|
|
278
|
+
## Telemetria
|
|
279
|
+
|
|
280
|
+
Quatro séries, por modelo, e cada uma responde a uma pergunta que alguém vai fazer:
|
|
281
|
+
|
|
282
|
+
| Série | Pergunta |
|
|
283
|
+
|---|---|
|
|
284
|
+
| Latência | "Por que o cliente ainda não recebeu?" |
|
|
285
|
+
| Custo | "Quanto gastamos com isto no mês?" |
|
|
286
|
+
| Taxa de rejeição por política | "Nosso prompt está pedindo o que o provedor não faz?" |
|
|
287
|
+
| Taxa de aprovação humana | "O modelo que escolhemos serve para este trabalho?" |
|
|
288
|
+
|
|
289
|
+
A última é a que ninguém instrumenta e a que mais decide: um modelo com 30 % de aprovação humana é
|
|
290
|
+
mais caro que um modelo com o dobro da tarifa e 90 %.
|
|
291
|
+
|
|
292
|
+
---
|
|
293
|
+
|
|
294
|
+
## Testes
|
|
295
|
+
|
|
296
|
+
- **Nenhum teste chama API paga.** Provider fake implementando a mesma abstração interna, store em
|
|
297
|
+
memória. Isso não é preferência: é a única forma de a suíte rodar em CI sem chave e sem fatura.
|
|
298
|
+
- O que se testa é o **mecanismo**: que `Publish` falha fora de `Approved`; que `RejectedByPolicy`
|
|
299
|
+
não oferece retry; que a chave de pedido é estável para o mesmo pedido e muda quando qualquer campo
|
|
300
|
+
participante muda; que gravar o mesmo conteúdo duas vezes grava uma.
|
|
301
|
+
- **Teste de acessibilidade por reflexão** para a regra dura: o tipo que produz bytes não é público.
|
|
302
|
+
Torná-lo público tem de derrubar esse teste — e vale rodar a mutação uma vez para ver.
|
|
303
|
+
|
|
304
|
+
---
|
|
305
|
+
|
|
306
|
+
## Checklist (verifiable by morph-eval)
|
|
307
|
+
|
|
308
|
+
- [ ] Nenhum handler síncrono consegue nomear o tipo que produz bytes
|
|
309
|
+
- [ ] Nenhum `await runner.RunAsync(...)` dentro de handler de turno — **o tipo não fecha esta
|
|
310
|
+
porta** (o runner é público de propósito); quem a fecha é a revisão de código
|
|
311
|
+
- [ ] A superfície pública devolve id de job, nunca bytes
|
|
312
|
+
- [ ] Os oito estados existem, e `Publish` falha fora de `Approved`
|
|
313
|
+
- [ ] `Publish` recusa sem marcação quando a finalidade a exige — e o teste dessa recusa existe
|
|
314
|
+
- [ ] Bloqueio de moderação é `rejected_by_policy`, sem retry
|
|
315
|
+
- [ ] Chave de **pedido** consultada antes da chamada paga; chave de **conteúdo** endereça o storage
|
|
316
|
+
- [ ] Bytes no blob próprio; banco com caminho relativo + sha256
|
|
317
|
+
- [ ] Proveniência com os nove campos, C2PA preservado sem re-encode
|
|
318
|
+
- [ ] Marcação visível aplicada no ponto de publicação, com texto **e** superfície nomeados
|
|
319
|
+
- [ ] `Approve` carimba revisor e data
|
|
320
|
+
- [ ] `estimatedCostUsd` gravado antes da chamada; teto por tenant/dia recusa no enqueue
|
|
321
|
+
- [ ] Telemetria com as quatro séries, incluindo taxa de aprovação humana
|
|
322
|
+
- [ ] Nenhum teste toca API paga
|
|
323
|
+
|
|
324
|
+
---
|
|
325
|
+
|
|
326
|
+
## Como re-verificar este standard
|
|
327
|
+
|
|
328
|
+
| Página | O que conferir |
|
|
329
|
+
|---|---|
|
|
330
|
+
| `https://developers.openai.com/api/docs/guides/content-provenance` | Se `content_provenance_check` mudou, e a afirmação de que C2PA cai com re-encode |
|
|
331
|
+
| `https://ai.google.dev/gemini-api/docs/image-generation` | Se SynthID continua em toda imagem Gemini |
|
|
332
|
+
| `https://eur-lex.europa.eu/eli/reg/2024/1689/oj` | O art. 50 e o art. 113 no texto oficial — é a fonte primária que a §EU AI Act ainda não tem |
|
|
333
|
+
| `https://ai.google.dev/gemini-api/docs/veo` | A retenção de 2 dias citada em §Storage |
|
|
334
|
+
| `modalities-image-gen.md` e `media-video.md` | As tabelas de preço que este standard referencia sem copiar |
|
|
335
|
+
|
|
336
|
+
Ao terminar, atualize `Last-verified` **e** o `ai-pin` citado no header.
|
|
337
|
+
|
|
338
|
+
---
|
|
339
|
+
|
|
340
|
+
## References
|
|
341
|
+
|
|
342
|
+
- `ai-agents/modalities-image-gen.md` — a chamada de imagem, os aliases e o custo
|
|
343
|
+
- `ai-agents/media-video.md` — a chamada de vídeo, o polling e o custo por segundo
|
|
344
|
+
- `backend/integrations/hangfire/hangfire-jobs.md` — o mecanismo de job: enqueue, retry,
|
|
345
|
+
`IDbContextFactory`, dashboard. Este standard **cita** e não reescreve
|
|
346
|
+
- `ai-agents/durable-workflows-hitl.md` — HITL dentro de um Workflow MAF; a outra coisa
|
|
347
|
+
- `ai-agents/production.md` — custo por chamada, teste sem rede, observabilidade
|
|
348
|
+
- `ai-agents/batching.md` — o desconto de lote que o catálogo usa
|
|
349
|
+
|
|
350
|
+
---
|
|
351
|
+
|
|
352
|
+
*MORPH-SPEC by Polymorphism Tech — ai-agents/media-pipeline.md v1.0*
|