@polymorphism-tech/morph-spec 8.34.2 → 8.35.1
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 +22 -5
- 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 +236 -11
- 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/core/worktree-env-inject.js +43 -0
- 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/payload-utils.js +15 -2
- 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 +148 -6
- package/src/commands/project/update.js +469 -153
- package/src/commands/project/worktree.js +76 -4
- 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 +379 -24
- 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/git/pr-files.js +56 -0
- 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
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
# LLM Runtime Defaults — timeout, retry, strict, amostragem e o pin do SDK
|
|
2
|
+
|
|
3
|
+
> **Scope:** stacks=["dotnet"]
|
|
4
|
+
> **Layer:** 1 (on-keyword)
|
|
5
|
+
> **Keywords:** llm defaults, runtime defaults, timeout llm, retry llm, strict json schema, temperature reasoning, capability por alias, network timeout, pin de sdk
|
|
6
|
+
> **Read by Claude in:** implement (ao configurar cliente, alias ou opções de chamada) e troubleshoot (chamada pendurada, 400 recorrente, quebra binária)
|
|
7
|
+
|
|
8
|
+
**Verified against:** Microsoft.Extensions.AI 10.9.0 + Microsoft.Agents.AI 1.20.0 + OpenAI 2.13.0 (ai-pin 2026-09-08); provado por `templates/dotnet/ai-kit/src/Morph.AiKit/Providers/ModelAlias.cs` e `.../Providers/ModelRegistry.cs` (alias, `api:`, e limite por alias com procedência obrigatória). A superfície do SDK citada aqui — `ChatOptions`, `ChatResponseFormatJson`, `ReasoningEffort`, `OpenAIClientOptions` — foi **medida por reflexão sobre as assemblies do pin** em 2026-09-08. O timeout é **provado por** `.../Agents/AgentSpecOptions.cs` e `.../Agents/AgentFactory.cs`, que o kit compila **por spec** (`TimeoutSeconds` vira um cliente de timeout no pipeline) — e **não** por alias: a allowlist de alias do registry não tem chave de timeout (medido). Os valores default do retry do `System.ClientModel` 1.15.0 são **verificação documental** — essa assembly está fora do conjunto que o probe carrega. Last-verified: 2026-09-08.
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## Fronteira com o Model Registry
|
|
13
|
+
|
|
14
|
+
`ai-agents-providers-model-registry` é **Layer 0** (sempre carregado) e continua dono do **schema**:
|
|
15
|
+
o formato do documento, `defaultAlias`, o fallback e a tabela de providers. **Este** standard é dono
|
|
16
|
+
dos **valores e dos botões de runtime**: timeout, retry, strict, amostragem, esforço de raciocínio e
|
|
17
|
+
o pin de versão do SDK.
|
|
18
|
+
|
|
19
|
+
Sem esta fronteira escrita, o par vira **duas verdades sobre o mesmo JSON** — e a segunda verdade é
|
|
20
|
+
sempre a que alguém encontra primeiro.
|
|
21
|
+
|
|
22
|
+
Complemento: `ai-agents-agent-spec` é dono da **forma** do agente e da regra "nulo = não envia";
|
|
23
|
+
`ai-agents-cost-and-budget` é dono de `pricing`. Aqui não se repete nenhum dos três.
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## Retry herdado
|
|
28
|
+
|
|
29
|
+
**Não escreva um loop de retry sobre chamada de LLM.** A pilha do `System.ClientModel` — a base dos
|
|
30
|
+
clientes gerados da OpenAI — já traz uma política de retry, e ela é aplicada por padrão.
|
|
31
|
+
|
|
32
|
+
O que a assembly `System.ClientModel` 1.15.0 (a restaurada junto com o pin) carrega nos metadados,
|
|
33
|
+
**medido por leitura de literal em 2026-09-08**: `ClientRetryPolicy`, `ClientPipelineOptions`,
|
|
34
|
+
`RetryPolicy`, `MaxRetries`, `DefaultMaxRetries`, `DefaultInitialDelay`, `ShouldRetry`,
|
|
35
|
+
`GetNextDelay`. Isto prova que os pontos de extensão existem e como se chamam.
|
|
36
|
+
|
|
37
|
+
**Verificação documental** (fonte primária: o fonte de `ClientRetryPolicy` em
|
|
38
|
+
`Azure/azure-sdk-for-net`, lido em 2026-09-08), e por isso escrita como valor a **conferir** antes de
|
|
39
|
+
depender dela: 3 tentativas de retry, atraso inicial de 0,8 s, backoff exponencial na forma
|
|
40
|
+
`(1 << (tryCount - 1)) * initialDelay`, e o cabeçalho de espera do servidor respeitado quando ele
|
|
41
|
+
pede mais tempo do que o backoff calculado.
|
|
42
|
+
|
|
43
|
+
**A regra:** herde. Se precisar de outro número, **substitua a política** (`RetryPolicy` nas opções
|
|
44
|
+
do cliente), não empilhe um `for` por cima. Duas camadas de retry multiplicam: 3 × 3 = 9 chamadas
|
|
45
|
+
pagas para um incidente que o operador vê como "uma".
|
|
46
|
+
|
|
47
|
+
Prática de campo alinhada, com a razão escrita no próprio código: *"não adicionamos loop próprio"*.
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
## Timeout explícito
|
|
52
|
+
|
|
53
|
+
**Retry sobre uma chamada que nunca expira é o pior dos dois mundos.** A política tenta de novo o
|
|
54
|
+
que ainda não desistiu, e o incidente aparece como latência infinita em vez de erro.
|
|
55
|
+
|
|
56
|
+
Dois fatos medidos por reflexão sobre as assemblies do pin, em 2026-09-08:
|
|
57
|
+
|
|
58
|
+
1. **`Microsoft.Extensions.AI.ChatOptions` não tem propriedade de timeout.** As 20 propriedades
|
|
59
|
+
declaradas são de conteúdo da chamada (`Temperature`, `TopP`, `TopK`, `MaxOutputTokens`,
|
|
60
|
+
`ResponseFormat`, `Tools`, `ToolMode`, `Reasoning`, `Seed`, `StopSequences`, `Instructions`,
|
|
61
|
+
`ModelId`, `ConversationId`, `AdditionalProperties`, …). A abstração **não sabe expressar**
|
|
62
|
+
timeout — logo, ele não é um botão por chamada nesse nível.
|
|
63
|
+
2. **`OpenAI.OpenAIClientOptions` (OpenAI 2.13.0) declara apenas** `Endpoint`, `OrganizationId`,
|
|
64
|
+
`ProjectId` e `UserAgentApplicationId`. O botão de timeout **não é dele**: ele vem da base,
|
|
65
|
+
`System.ClientModel.Primitives.ClientPipelineOptions`, cuja assembly carrega os nomes
|
|
66
|
+
`NetworkTimeout` e `get_NetworkTimeout` (medido por literal na mesma data). A declaração está
|
|
67
|
+
fora do conjunto de assemblies que o probe carrega, então este ponto é **documental**.
|
|
68
|
+
|
|
69
|
+
**A regra, em três partes:**
|
|
70
|
+
|
|
71
|
+
- **Configure o timeout explicitamente**, e escolha conscientemente a camada. O exemplar do kit o faz **por spec de agente** (`AgentSpecOptions.TimeoutSeconds` → um cliente de timeout no pipeline), porque a allowlist de alias do registry **não tem** chave de timeout — medido. Por alias exige abrir essa allowlist, o que é mudança de `.cs`. Alias
|
|
72
|
+
de raciocínio pesado e alias de resposta curta não têm o mesmo tempo aceitável.
|
|
73
|
+
- **`CancellationToken` de turno não é timeout de chamada.** Ele cancela quando *alguém* desiste
|
|
74
|
+
(o usuário fechou a aba, o job foi abortado). Uma chamada pendurada sem ninguém para desistir
|
|
75
|
+
fica pendurada.
|
|
76
|
+
- **Timeout curto sem retry é fragilidade; retry sem timeout é vazamento.** Os dois andam juntos.
|
|
77
|
+
|
|
78
|
+
Medições que motivam a regra: um projeto do acervo tem **apenas** o `CancellationToken` do turno,
|
|
79
|
+
sem nenhum timeout de chamada. Outro tem uma biblioteca de resiliência declarada no `.csproj`
|
|
80
|
+
**sem aplicá-la à camada de IA**, e nenhum timeout de `HttpClient` nem handler de resiliência
|
|
81
|
+
padrão registrado.
|
|
82
|
+
|
|
83
|
+
> **Correção explícita de premissa.** A formulação "timeout é herdado do SDK, como o retry" é
|
|
84
|
+
> **falsa** nas duas pontas medidas: o retry é herdado, o timeout precisa ser **decidido**. Herdar
|
|
85
|
+
> o que não existe é como se descobre que uma chamada roda até o processo morrer.
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
## Strict JSON schema por alias
|
|
90
|
+
|
|
91
|
+
O identificador **`StrictJsonSchema` não existe**. Medição, 2026-09-08: uma varredura por reflexão
|
|
92
|
+
sobre as **14 assemblies** dos pacotes do pin e das pontes (`Microsoft.Agents.AI` e derivados,
|
|
93
|
+
`Microsoft.Extensions.AI` e derivados, `OpenAI`, `Google.GenAI`, `ModelContextProtocol` e derivados,
|
|
94
|
+
`Microsoft.Extensions.VectorData.Abstractions`) devolve **zero** tipos exportados cujo nome contenha
|
|
95
|
+
`Strict`.
|
|
96
|
+
|
|
97
|
+
E `Microsoft.Extensions.AI.ChatResponseFormatJson` declara exatamente três propriedades — `Schema`,
|
|
98
|
+
`SchemaDescription`, `SchemaName` — e **nenhum campo `strict`**, também medido por reflexão. A
|
|
99
|
+
abstração não sabe expressar strict.
|
|
100
|
+
|
|
101
|
+
O mecanismo real é **uma chave em `ChatOptions.AdditionalProperties`**, lida pela ponte do provider,
|
|
102
|
+
que transforma o schema antes de enviá-lo (proibir propriedades adicionais, converter schemas
|
|
103
|
+
booleanos). Isso significa três coisas para o desenho:
|
|
104
|
+
|
|
105
|
+
- **Strict é decisão por chamada / por alias**, porque é onde `ChatOptions` vive.
|
|
106
|
+
- **Suporte a strict é capacidade do modelo**, e o registry já sabe o provider e o modelo de cada
|
|
107
|
+
alias. Logo o lugar do "este alias suporta strict" é o **alias**.
|
|
108
|
+
- **Nunca uma flag global de processo.**
|
|
109
|
+
|
|
110
|
+
### O anti-padrão, com o nome real do campo
|
|
111
|
+
|
|
112
|
+
Medido em produção no acervo: um par `StrictJsonSchemaSupported` (propriedade de configuração) +
|
|
113
|
+
`volatile bool _strictUnsupported` (campo estático de processo). Ao receber um `400` de qualquer
|
|
114
|
+
chamada, o campo é ligado e **todas as chamadas seguintes do processo** passam a ser enviadas sem
|
|
115
|
+
strict. A frase do próprio diagnóstico do projeto: *"um 400 em qualquer ponto degrada todas as
|
|
116
|
+
chamadas seguintes"*.
|
|
117
|
+
|
|
118
|
+
O efeito prático: um modelo local em desenvolvimento, que legitimamente não suporta strict, rebaixa
|
|
119
|
+
as chamadas de **produção** do mesmo processo. Capacidade é do alias; degradação global é um bug
|
|
120
|
+
disfarçado de resiliência.
|
|
121
|
+
|
|
122
|
+
O kit compila a forma correta dessa ideia: limites conhecidos de um alias vivem num record de
|
|
123
|
+
`Constraints` **por alias**, e um limite **sem procedência escrita é recusado na carga do
|
|
124
|
+
registry** — para que ninguém consiga gravar um "todo mundo sabe que" sem dizer de onde tirou.
|
|
125
|
+
|
|
126
|
+
---
|
|
127
|
+
|
|
128
|
+
## Temperature e reasoning
|
|
129
|
+
|
|
130
|
+
**Modelo de raciocínio e amostragem não se misturam.** A regra prática: `Temperature` só faz sentido
|
|
131
|
+
em modelo sem raciocínio; em modelo de raciocínio o botão é o **esforço**.
|
|
132
|
+
|
|
133
|
+
O que está **medido por reflexão** sobre `Microsoft.Extensions.AI.Abstractions` 10.9.0, em
|
|
134
|
+
2026-09-08:
|
|
135
|
+
|
|
136
|
+
- `ChatOptions.Temperature` (`float?`) e `ChatOptions.Reasoning` (`ReasoningOptions`) são
|
|
137
|
+
propriedades **distintas** e independentes.
|
|
138
|
+
- `ReasoningOptions` declara `Effort` e `Output`.
|
|
139
|
+
- `ReasoningEffort` é um **enum de primeira classe** com exatamente cinco valores:
|
|
140
|
+
`None = 0`, `Low = 1`, `Medium = 2`, `High = 3`, `ExtraHigh = 4`.
|
|
141
|
+
|
|
142
|
+
Esforço de raciocínio, portanto, é **tipado** — não é string, e não precisa de convenção de projeto.
|
|
143
|
+
|
|
144
|
+
A **medição de campo** que sustenta o limite prático (dois modelos de raciocínio que rejeitam
|
|
145
|
+
`Temperature != 1` quando há tools na chamada) é de `ai-agents-providers-model-registry` — Layer 0,
|
|
146
|
+
sempre carregado, e dono dela desde a re-verificação anterior. **Não é repetida aqui**: uma segunda
|
|
147
|
+
cópia da mesma medição é a segunda verdade que a seção de fronteira acima existe para evitar. O que
|
|
148
|
+
este standard acrescenta é onde o limite mora e o que ele governa.
|
|
149
|
+
|
|
150
|
+
**Contra-evidência, e ela é instrutiva:** outro projeto do acervo **não configura parâmetro de
|
|
151
|
+
amostragem nenhum** e roda no default do SDK. Não configurar é uma escolha válida, e mais honesta
|
|
152
|
+
que configurar errado. A regra final é: **configure quando você mediu que precisa; caso contrário,
|
|
153
|
+
não envie** (`ai-agents-agent-spec`, "nulo = não envia").
|
|
154
|
+
|
|
155
|
+
Onde o limite mora: no **alias**, como `Constraints` com procedência — a mesma forma que o kit
|
|
156
|
+
compila para `ToolCallingRequiresReasoningEffortNone` e `TemperatureUnsupported`. Um limite por
|
|
157
|
+
alias é verificável antes da chamada; um limite espalhado em `if`s só é verificável depois do 400.
|
|
158
|
+
|
|
159
|
+
---
|
|
160
|
+
|
|
161
|
+
## Pin de SDK e compatibilidade binária
|
|
162
|
+
|
|
163
|
+
**Faixa flutuante em SDK de IA custa dinheiro.** Não é uma preferência de estilo: é um incidente
|
|
164
|
+
medido.
|
|
165
|
+
|
|
166
|
+
O caso, do acervo: um projeto referenciava o SDK da OpenAI numa faixa `2.*`. O NuGet resolveu para
|
|
167
|
+
uma versão menor mais nova, um membro de conteúdo de resposta **mudou de assinatura**, e a chamada
|
|
168
|
+
estourou `MissingMethodException` **depois de a requisição já ter sido paga** — o dinheiro saiu, a
|
|
169
|
+
resposta não chegou ao domínio. A correção foi pinar a versão exata, com oito linhas de comentário
|
|
170
|
+
explicando por quê.
|
|
171
|
+
|
|
172
|
+
**As três regras:**
|
|
173
|
+
|
|
174
|
+
1. **Pin exato** (`[2.13.0]`, não `2.*`) para todo pacote de IA. Neste framework a fonte única é
|
|
175
|
+
`framework/ai-pin.json`, e nenhum standard escreve versão à mão.
|
|
176
|
+
2. **A faixa e o pacote de ponte andam juntos.** `Microsoft.Extensions.AI.OpenAI` referencia uma
|
|
177
|
+
versão do `OpenAI`; carregar outra em runtime é uma quebra binária esperando um caminho de código
|
|
178
|
+
pouco exercitado.
|
|
179
|
+
3. **Teste de compatibilidade binária como rede de segurança** — comparar a versão do assembly
|
|
180
|
+
carregado com a que a ponte referencia, e conferir a **assinatura** do membro que já quebrou uma
|
|
181
|
+
vez. A técnica está em `ai-agents-testing-ai`.
|
|
182
|
+
|
|
183
|
+
---
|
|
184
|
+
|
|
185
|
+
## Anti-patterns
|
|
186
|
+
|
|
187
|
+
| Anti-pattern | Por quê é problema | Solução |
|
|
188
|
+
|---|---|---|
|
|
189
|
+
| Loop de retry próprio sobre a chamada de LLM | Multiplica com o retry do SDK: 3 × 3 = 9 chamadas pagas por incidente | Herde; para outro número, substitua a política |
|
|
190
|
+
| Chamada de LLM sem timeout | Retry sobre o que nunca expira; o incidente vira latência infinita | Timeout explícito — por spec de agente (o exemplar do kit) ou por alias, se a allowlist foi aberta |
|
|
191
|
+
| `CancellationToken` de turno usado como timeout | Só cancela quando alguém desiste; ninguém desiste de um job noturno | Timeout explícito, além do token |
|
|
192
|
+
| Flag global de processo para strict | Um 400 em dev rebaixa produção no mesmo processo | Capacidade por alias, em `Constraints` com procedência |
|
|
193
|
+
| `Temperature` em modelo de raciocínio | Erro do provider, ou pior: silenciosamente ignorado | Esforço tipado (`ReasoningEffort`) para raciocínio; amostragem só sem raciocínio |
|
|
194
|
+
| Parâmetro de amostragem configurado "por garantia" | Envia valor que ninguém mediu, e some no default do provider | Nulo = não envia |
|
|
195
|
+
| Faixa flutuante (`2.*`) em pacote de IA | Quebra binária depois da chamada paga | Pin exato, a partir de `framework/ai-pin.json` |
|
|
196
|
+
| Limite de alias escrito como regra universal em C# | Vira folclore sem procedência, e ninguém sabe revogá-lo | Campo do alias, com procedência obrigatória |
|
|
197
|
+
|
|
198
|
+
---
|
|
199
|
+
|
|
200
|
+
## Checklist (verifiable by morph-eval)
|
|
201
|
+
|
|
202
|
+
- [ ] Nenhum loop de retry escrito à mão em volta de uma chamada de LLM
|
|
203
|
+
- [ ] Há timeout explícito (por spec de agente, como o exemplar do kit, ou por alias se a allowlist foi aberta), e ele **não** é o `CancellationToken` do turno
|
|
204
|
+
- [ ] Nenhuma flag estática de processo governa strict ou qualquer outra capacidade
|
|
205
|
+
- [ ] Capacidade e limite são campos do **alias**, com procedência escrita
|
|
206
|
+
- [ ] Nenhuma ocorrência de um tipo chamado `StrictJsonSchema` (ele não existe em nenhum pacote do pin)
|
|
207
|
+
- [ ] Esforço de raciocínio usa o enum `ReasoningEffort`, não string
|
|
208
|
+
- [ ] `Temperature` não é enviada junto com esforço de raciocínio
|
|
209
|
+
- [ ] Todo pacote de IA está pinado em versão exata, derivada de `framework/ai-pin.json`
|
|
210
|
+
- [ ] Existe um teste de compatibilidade binária cobrindo o par SDK × ponte
|
|
211
|
+
|
|
212
|
+
---
|
|
213
|
+
|
|
214
|
+
## References
|
|
215
|
+
|
|
216
|
+
- `ai-agents-providers-model-registry` — Layer 0: o **schema** do documento, `defaultAlias`, fallback
|
|
217
|
+
e a tabela de providers. Este standard não repete nada disso
|
|
218
|
+
- `ai-agents-agent-spec` — a forma do agente e a regra "nulo = não envia"
|
|
219
|
+
- `ai-agents-cost-and-budget` — `pricing` por alias, cálculo e teto de gasto
|
|
220
|
+
- `ai-agents-testing-ai` — o teste de compatibilidade binária, e como exercitar opções sem rede
|
|
221
|
+
- `ai-agents-structured-output` — o schema da saída, cujo strict este standard governa
|
|
222
|
+
- `framework/ai-pin.json` — a fonte única das versões; nenhuma versão é digitada num standard
|
|
223
|
+
|
|
224
|
+
---
|
|
225
|
+
|
|
226
|
+
*MORPH-SPEC by Polymorphism Tech — ai-agents/llm-runtime-defaults.md v1.0 (2026-09-08)*
|
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
> **Scope:** stacks=["dotnet"]
|
|
4
4
|
> **Layer:** 2 (on-keyword)
|
|
5
|
-
> **Keywords:** mcp server, expose mcp, build mcp server, mcp host, publish tools, McpServerTool, AddMcpServer
|
|
5
|
+
> **Keywords:** mcp server, expose mcp, build mcp server, mcp host, publish tools, McpServerTool, AddMcpServer, request filters, stateless, spec 2026-07-28
|
|
6
6
|
> **Read by Claude in:** implement (quando um projeto expõe capacidades como MCP server para consumo externo)
|
|
7
7
|
|
|
8
|
-
**Verified against:**
|
|
8
|
+
**Verified against:** ModelContextProtocol 2.2.0 + ModelContextProtocol.AspNetCore 2.2.0 (ai-pin 2026-09-08; o `.AspNetCore` não está no pin — versão apurada no nuget.org em 2026-09-08) + revisão de spec MCP **2026-07-28** (modelcontextprotocol.io/specification/versioning, lido 2026-09-08). **Verificação documental — o ai-kit não exercita MCP**, e por isso este standard NÃO carimba `provado por`. Os nomes de tipo, os defaults e os avisos de obsolescência abaixo foram **medidos por reflexão sobre as assemblies 2.2.0** em 2026-09-08. Last-verified: 2026-09-08.
|
|
9
9
|
|
|
10
10
|
---
|
|
11
11
|
|
|
@@ -30,26 +30,63 @@ Crie um MCP server quando você quer **expor capacidades do projeto** de forma p
|
|
|
30
30
|
|
|
31
31
|
## A API
|
|
32
32
|
|
|
33
|
+
### Não existe "MCP 2.0" como revisão de especificação
|
|
34
|
+
|
|
35
|
+
A confusão vale ser desfeita antes de qualquer código, porque ela muda o que se procura na documentação:
|
|
36
|
+
|
|
37
|
+
| Coisa | Como é versionada | Valor corrente (2026-09-08) |
|
|
38
|
+
|---|---|---|
|
|
39
|
+
| **A especificação MCP** | por **data** | revisão **`2026-07-28`** (sucede `2025-11-25`) |
|
|
40
|
+
| **O SDK C# `ModelContextProtocol`** | SemVer | **2.2.0**, publicado 2026-08-13 |
|
|
41
|
+
|
|
42
|
+
"MCP 2.0" é a **major do SDK**, nunca uma revisão de spec. Fonte: modelcontextprotocol.io/specification/versioning e o changelog da revisão `2026-07-28`, lidos em 2026-09-08.
|
|
43
|
+
|
|
44
|
+
### O que a revisão `2026-07-28` mudou para quem escreve servidor
|
|
45
|
+
|
|
46
|
+
- **Sessões removidas** — o cabeçalho `Mcp-Session-Id` deixou de existir (**SEP-2567**).
|
|
47
|
+
- **`initialize` / `notifications/initialized` removidos** — versão e capacidades viajam em `_meta` **por request** (**SEP-2575**).
|
|
48
|
+
- Novo RPC **`server/discover`**.
|
|
49
|
+
- **`ping`, `logging/setLevel` e `notifications/roots/list_changed` removidos.**
|
|
50
|
+
- **Roots, Sampling e Logging deprecados** (**SEP-2577**).
|
|
51
|
+
- **Tasks** (long-running) saíram do core para a extensão `io.modelcontextprotocol/tasks`.
|
|
52
|
+
- **Elicitation/sampling substituídos por MRTR** — `InputRequiredResult` + `InputRequest.ForElicitation(...)` (**SEP-2322**).
|
|
53
|
+
- **Resultado cacheável** — `ICacheableResult` com `TimeToLive` e `CacheScope` (**SEP-2549**).
|
|
54
|
+
- **HTTP+SSE formalmente Deprecated** (Streamable HTTP é o transporte).
|
|
55
|
+
|
|
56
|
+
> **Duas dessas afirmações não dependem do changelog: elas estão gravadas na assembly.** Medido em `ModelContextProtocol.AspNetCore` 2.2.0 e `ModelContextProtocol.Core` 2.2.0, no texto do `[Obsolete]` de cada membro:
|
|
57
|
+
> - `HttpServerTransportOptions.EventStreamStore`/`IdleTimeout`/`MaxIdleSessionCount`/`PerSessionExecutionContext`/`SessionMigrationHandler` — *"Stateful Streamable HTTP mode is a back-compat-only escape hatch for 2025-11-25 protocol revision clients and earlier. Set `HttpServerTransportOptions.SessionMode = HttpServerSessionMode.Stateless` (**the default as of the 2026-07-28 protocol revision**) for new code. See SEP-2567."*
|
|
58
|
+
> - `McpServerOptions.MaxSamplingOutputTokens` — *"The Sampling feature is deprecated as of specification version 2026-07-28 … See SEP-2577."*
|
|
59
|
+
> - `HttpServerTransportOptions.EnableLegacySse` — obsoleto: *"…Use Streamable HTTP instead."*
|
|
60
|
+
|
|
61
|
+
### A API C# de servidor NÃO mudou de nome
|
|
62
|
+
|
|
63
|
+
`AddMcpServer()`, `WithStdioServerTransport()`, `WithHttpTransport(...)`, `WithToolsFromAssembly()`, `WithTools([...])`, `[McpServerToolType]`, `[McpServerTool]`, `McpServerTool.Create(...)` e `app.MapMcp()` continuam iguais. **O que mudou é o default**, não a grafia.
|
|
64
|
+
|
|
33
65
|
**Packages:**
|
|
34
66
|
|
|
35
67
|
```xml
|
|
36
|
-
<!-- SDK cliente+servidor do protocolo MCP -->
|
|
37
|
-
<PackageReference Include="ModelContextProtocol" Version="0
|
|
68
|
+
<!-- SDK cliente+servidor do protocolo MCP — no ai-pin.json -->
|
|
69
|
+
<PackageReference Include="ModelContextProtocol" Version="2.2.0" />
|
|
38
70
|
|
|
39
|
-
<!-- Pacote base MAF (para AsAIAgent, AsAIFunction) -->
|
|
40
|
-
<PackageReference Include="Microsoft.Agents.AI" Version="1.0
|
|
71
|
+
<!-- Pacote base MAF (para AsAIAgent, AsAIFunction) — no ai-pin.json -->
|
|
72
|
+
<PackageReference Include="Microsoft.Agents.AI" Version="1.20.0" />
|
|
41
73
|
|
|
42
|
-
<!-- Apenas se o transporte for HTTP (server-side)
|
|
43
|
-
|
|
74
|
+
<!-- Apenas se o transporte for HTTP (server-side).
|
|
75
|
+
NÃO está no ai-pin.json; versão apurada no nuget.org em 2026-09-08. -->
|
|
76
|
+
<PackageReference Include="ModelContextProtocol.AspNetCore" Version="2.2.0" />
|
|
44
77
|
```
|
|
45
78
|
|
|
46
|
-
|
|
79
|
+
### Stateless é o DEFAULT, não uma escolha
|
|
80
|
+
|
|
81
|
+
Medido em `ModelContextProtocol.AspNetCore` 2.2.0, instanciando `HttpServerTransportOptions` e lendo os valores iniciais: **`SessionMode == HttpServerSessionMode.Stateless`** e `Stateless == true`. Os valores de `HttpServerSessionMode` são `Stateless` (0), `Stateful` (1) e `StatefulForInitializeClients` (2).
|
|
82
|
+
|
|
83
|
+
Escrever `o.Stateless = true` hoje é redundante; escrever `o.SessionMode = HttpServerSessionMode.Stateful` é **optar por um escape hatch de compatibilidade** com clientes da revisão `2025-11-25` e anteriores — e é isso que a mensagem de obsolescência diz. A versão anterior deste standard apresentava stateless como uma decisão de escala do autor; o protocolo já a tomou.
|
|
47
84
|
|
|
48
85
|
**Dois jeitos de declarar tools:**
|
|
49
86
|
|
|
50
87
|
| Padrão | Quando usar |
|
|
51
88
|
|--------|-------------|
|
|
52
|
-
| Atributos `[McpServerToolType]` + `[McpServerTool]` | Tools são métodos
|
|
89
|
+
| Atributos `[McpServerToolType]` + `[McpServerTool]` | Tools são métodos do projeto — padrão canônico do SDK. Descoberta automática via `WithToolsFromAssembly()`. |
|
|
53
90
|
| `McpServerTool.Create(...)` | Embrulhar um agente MAF (`agent.AsAIFunction()`) ou um `AIFunction` construído em runtime como tool. |
|
|
54
91
|
|
|
55
92
|
**Padrão de servidor (stdio):**
|
|
@@ -63,7 +100,7 @@ Tools ([McpServerTool] ou McpServerTool.Create)
|
|
|
63
100
|
→ Host.Build().RunAsync() // sobe o servidor
|
|
64
101
|
```
|
|
65
102
|
|
|
66
|
-
**Transport stdio** é o padrão para servidores locais (subprocessos, Claude Code tools). **HTTP server-side** usa o pacote `ModelContextProtocol.AspNetCore`: troque `WithStdioServerTransport()` por `WithHttpTransport(
|
|
103
|
+
**Transport stdio** é o padrão para servidores locais (subprocessos, Claude Code tools). **HTTP server-side** usa o pacote `ModelContextProtocol.AspNetCore`: troque `WithStdioServerTransport()` por `WithHttpTransport()` e exponha o endpoint com `app.MapMcp()` num `WebApplication`.
|
|
67
104
|
|
|
68
105
|
---
|
|
69
106
|
|
|
@@ -148,7 +185,7 @@ var builder = WebApplication.CreateBuilder(args);
|
|
|
148
185
|
|
|
149
186
|
builder.Services
|
|
150
187
|
.AddMcpServer()
|
|
151
|
-
.WithHttpTransport(
|
|
188
|
+
.WithHttpTransport() // SessionMode = Stateless já é o default (medido em 2.2.0)
|
|
152
189
|
.WithToolsFromAssembly();
|
|
153
190
|
|
|
154
191
|
var app = builder.Build();
|
|
@@ -157,9 +194,64 @@ app.MapMcp(); // expõe o endpoint MCP (Streamable HTTP)
|
|
|
157
194
|
app.Run();
|
|
158
195
|
```
|
|
159
196
|
|
|
160
|
-
> `Stateless = true
|
|
161
|
-
>
|
|
162
|
-
>
|
|
197
|
+
> Não escreva `options.Stateless = true`: é redundante desde a revisão `2026-07-28`. Se você
|
|
198
|
+
> precisar de `SessionMode = HttpServerSessionMode.Stateful`, saiba que está optando por um
|
|
199
|
+
> **escape hatch de compatibilidade** com clientes antigos — o próprio SDK diz isso no
|
|
200
|
+
> `[Obsolete]`. Para HTTP em produção, proteja `MapMcp()` com autenticação — ver seção Segurança.
|
|
201
|
+
|
|
202
|
+
---
|
|
203
|
+
|
|
204
|
+
## Filtros de request — listar não é poder chamar
|
|
205
|
+
|
|
206
|
+
Este é o mecanismo que permite **um servidor MCP servir vários tenants** sem um processo por tenant. A API foi medida em `ModelContextProtocol` 2.2.0 (`McpRequestFilterBuilderExtensions`) e `ModelContextProtocol.AspNetCore` 2.2.0 (`HttpMcpServerBuilderExtensions`).
|
|
207
|
+
|
|
208
|
+
```csharp
|
|
209
|
+
services.AddMcpServer()
|
|
210
|
+
.WithListToolsHandler(async (context, ct) => new ListToolsResult { Tools = GetTools() })
|
|
211
|
+
.WithRequestFilters(f =>
|
|
212
|
+
{
|
|
213
|
+
// (1) Poda a LISTAGEM — o cliente não vê a tool.
|
|
214
|
+
f.AddListToolsFilter(next => async (context, ct) =>
|
|
215
|
+
{
|
|
216
|
+
var result = await next(context, ct);
|
|
217
|
+
result.Tools = [.. result.Tools.Where(t => AllowedFor(context.User, t))];
|
|
218
|
+
return result;
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
// (2) Bloqueia a CHAMADA — sem isto, quem souber o nome chama assim mesmo.
|
|
222
|
+
f.AddCallToolFilter(next => async (context, ct) =>
|
|
223
|
+
{
|
|
224
|
+
if (!AllowedFor(context.User, context.Params!.Name)) // ClaimsPrincipal por request
|
|
225
|
+
throw new McpException("tool not available for this principal");
|
|
226
|
+
return await next(context, ct);
|
|
227
|
+
});
|
|
228
|
+
})
|
|
229
|
+
.AddAuthorizationFilters(); // a ORDEM importa — ver abaixo
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
**Duas regras que este standard existe para gravar:**
|
|
233
|
+
|
|
234
|
+
1. **São DOIS filtros, não um.** `AddListToolsFilter` **esconde** a tool; só `AddCallToolFilter` **impede chamá-la**. Um cliente que já conhece o nome — porque leu a lista antes, porque outro tenant tem a mesma tool, ou porque adivinhou — chama direto. Poda de listagem é ergonomia, não autorização.
|
|
235
|
+
2. **Cliente já conectado não relê a lista até reconectar.** Revogar acesso podando a listagem não revoga nada para quem já está dentro. A revogação real é o filtro de `CallTool`.
|
|
236
|
+
|
|
237
|
+
**A ordem do encadeamento é semântica:** um filtro registrado **antes** de `AddAuthorizationFilters()` roda com a lista **completa** — vê todas as tools, inclusive as que a autorização removeria. Se a intenção é filtrar o que já passou pela autorização, registre depois.
|
|
238
|
+
|
|
239
|
+
Filtros disponíveis (medidos): `AddListToolsFilter`, `AddCallToolFilter`, `AddListPromptsFilter`, `AddGetPromptFilter`, `AddListResourcesFilter`, `AddReadResourceFilter`, `AddListResourceTemplatesFilter`, `AddCompleteFilter`, `AddSubscribeToResourcesFilter`, `AddUnsubscribeFromResourcesFilter`, `AddSetLoggingLevelFilter`.
|
|
240
|
+
|
|
241
|
+
### Identidade por request
|
|
242
|
+
|
|
243
|
+
- **`context.User`** é o `ClaimsPrincipal` do request, disponível dentro do filtro.
|
|
244
|
+
- Uma tool pode receber por **injeção de parâmetro**: `ClaimsPrincipal`, `RequestContext<T>`, `McpServer` e `IProgress<T>`. O escopo de DI é **por request** — `McpServerOptions.ScopeRequests` tem default **`true`** (medido). `[FromKeyedServices]` funciona.
|
|
245
|
+
- **`HttpServerTransportOptions.ConfigureSessionOptions`** permite montar o `ToolCollection` a partir do `HttpContext.User` — poda no nascimento da sessão, complementar (não substituta) ao filtro de `CallTool`.
|
|
246
|
+
|
|
247
|
+
### Argumento de tool é input NÃO confiável
|
|
248
|
+
|
|
249
|
+
O que chega nos argumentos foi escrito por um modelo, a partir de texto que um humano digitou. Trate como entrada hostil:
|
|
250
|
+
|
|
251
|
+
- **Allow-list** de valores onde houver conjunto finito; nunca `switch` com `default:` permissivo.
|
|
252
|
+
- **Limite de tamanho** em toda string antes de tocar I/O.
|
|
253
|
+
- **Query parametrizada**, sempre — nunca concatenação com o argumento.
|
|
254
|
+
- **Id de tenant vem da closure ou da credencial, NUNCA do modelo.** Uma tool que aceita `tenantId` como parâmetro é uma tool que qualquer prompt injection reaponta para outro cliente.
|
|
163
255
|
|
|
164
256
|
**Registrar no Claude Code (`settings.json` do projeto consumidor):**
|
|
165
257
|
|
|
@@ -218,6 +310,10 @@ prefira o tipo de instância resolvido por DI a métodos estáticos com estado g
|
|
|
218
310
|
| Expor tools sem validação de input | Agentes externos (ou alucinações de LLM) podem enviar dados malformados | Validar todos os parâmetros antes de qualquer I/O |
|
|
219
311
|
| Tools sem escopo definido — expor tudo "por conveniência" | Superfície de ataque ampla; dificulta manutenção | Expor apenas o necessário; revisar a lista a cada release |
|
|
220
312
|
| HTTP transport sem autenticação | Qualquer processo na rede pode invocar as tools | Bearer token / API key obrigatório em HTTP; stdio é suficiente para uso local |
|
|
313
|
+
| **Podar só a listagem e chamar isso de autorização** | `ListTools` filtrado esconde a tool; quem sabe o nome chama assim mesmo, e cliente conectado não relê a lista | `AddListToolsFilter` **e** `AddCallToolFilter` |
|
|
314
|
+
| **`tenantId` como parâmetro de tool** | O argumento é escrito pelo modelo: prompt injection reaponta para outro cliente | Tenant vem da closure ou de `context.User` |
|
|
315
|
+
| Escrever `options.Stateless = true` "para escalar" | Redundante desde a revisão `2026-07-28`; sugere que há uma decisão a tomar onde não há | `WithHttpTransport()` sem argumento |
|
|
316
|
+
| Contar com `initialize`, `Mcp-Session-Id`, `ping` ou `logging/setLevel` | Removidos na revisão `2026-07-28` | Versão/capacidades em `_meta` por request; `server/discover` |
|
|
221
317
|
| Subir o MCP server no mesmo processo da aplicação principal | Acoplamento; falha no servidor MCP afeta a app | Projeto separado (`MyProject.McpServer`) com entrypoint próprio |
|
|
222
318
|
|
|
223
319
|
---
|
|
@@ -226,13 +322,16 @@ prefira o tipo de instância resolvido por DI a métodos estáticos com estado g
|
|
|
226
322
|
|
|
227
323
|
- [ ] `ModelContextProtocol` e `Microsoft.Agents.AI` no `.csproj`; `ModelContextProtocol.AspNetCore` apenas se HTTP
|
|
228
324
|
- [ ] Tools declaradas via `[McpServerToolType]` + `[McpServerTool]` (estáticas) ou `McpServerTool.Create(...)` (agente MAF / runtime)
|
|
229
|
-
- [ ] `AddMcpServer()` com `WithStdioServerTransport()` (stdio) ou `WithHttpTransport(
|
|
325
|
+
- [ ] `AddMcpServer()` com `WithStdioServerTransport()` (stdio) ou `WithHttpTransport()` (HTTP) — sem reafirmar o default `Stateless`
|
|
230
326
|
- [ ] `WithToolsFromAssembly()` para tools por atributo, ou `WithTools([...])` para tools de runtime
|
|
231
327
|
- [ ] Entrypoint: `await builder.Build().RunAsync()` (stdio) ou `app.MapMcp(); app.Run()` (HTTP)
|
|
232
328
|
- [ ] Agente criado via `_modelRegistry.GetChatClient("alias").AsAIAgent(...)` — provider-agnostic
|
|
233
329
|
- [ ] Validação de input em todas as tools antes de executar lógica de negócio
|
|
234
330
|
- [ ] Escopo mínimo: apenas tools necessárias para o consumidor externo
|
|
235
331
|
- [ ] HTTP transport (se usado) protegido por autenticação
|
|
332
|
+
- [ ] Multi-tenant: existe `AddCallToolFilter`, e não apenas `AddListToolsFilter`
|
|
333
|
+
- [ ] Nenhuma tool recebe id de tenant como parâmetro
|
|
334
|
+
- [ ] Nenhum `PackageReference` com faixa flutuante; pacote fora do pin com data de apuração
|
|
236
335
|
- [ ] Nenhum `Guid.NewGuid()` — usar `Guid.CreateVersion7()` se IDs são necessários
|
|
237
336
|
|
|
238
337
|
---
|
|
@@ -242,9 +341,11 @@ prefira o tipo de instância resolvido por DI a métodos estáticos com estado g
|
|
|
242
341
|
- `ai-agents-setup` — pacotes base MAF, DI, quick start
|
|
243
342
|
- `ai-agents-mcp-tools` — consumir MCP servers externos em um agente MAF
|
|
244
343
|
- `ai-agents-production` — middleware pipeline, `ResilientToolMiddleware`, segurança
|
|
245
|
-
- [ModelContextProtocol C# SDK](https://github.com/modelcontextprotocol/csharp-sdk)
|
|
344
|
+
- [ModelContextProtocol C# SDK](https://github.com/modelcontextprotocol/csharp-sdk) — `docs/concepts/filters.md`, `docs/concepts/identity/identity.md` (lidos 2026-09-08)
|
|
345
|
+
- [MCP — versionamento da especificação](https://modelcontextprotocol.io/specification/versioning) e o changelog da revisão `2026-07-28` (lidos 2026-09-08)
|
|
346
|
+
- [NuGet — ModelContextProtocol 2.2.0](https://www.nuget.org/packages/ModelContextProtocol/2.2.0) (publicado 2026-08-13)
|
|
246
347
|
- [Expose Agent as MCP Server — MAF docs](https://learn.microsoft.com/en-us/agent-framework/agents/tools/local-mcp-tools)
|
|
247
348
|
|
|
248
349
|
---
|
|
249
350
|
|
|
250
|
-
*MORPH-SPEC by Polymorphism Tech — ai-agents/mcp-server.md
|
|
351
|
+
*MORPH-SPEC by Polymorphism Tech — ai-agents/mcp-server.md v2.0 (2026-09-08)*
|