@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
|
@@ -15,6 +15,41 @@
|
|
|
15
15
|
* checagem por `existsSync` puro do `approve` aceitava um relatório SEM o token
|
|
16
16
|
* que o `gate-check` então descartava — o Gate 3 passava carimbado `auto` sobre
|
|
17
17
|
* uma média de auto-avaliação, exatamente o que MORPH.md §5 proíbe.
|
|
18
|
+
*
|
|
19
|
+
* ── O TOKEN VIGENTE É O ÚLTIMO ──────────────────────────────────────────────
|
|
20
|
+
*
|
|
21
|
+
* O `evaluator-report.md` é APPEND-ONLY por contrato: uma reavaliação acrescenta
|
|
22
|
+
* ao fim, preservando a análise anterior. Este módulo lia o COMEÇO (`String.match`
|
|
23
|
+
* com regex sem flag `g`), então num relatório reavaliado o gate era decidido
|
|
24
|
+
* pelo score SUPERADO. Medido em campo três vezes na mesma epic — #90 (8.7 →
|
|
25
|
+
* 9.4), #92 (8.2 → 9.0) e #93 (8.9 → 8.3 → 9.1) — e nas três o avaliador teve de
|
|
26
|
+
* desarmar o token antigo à mão para o gate ler a nota vigente.
|
|
27
|
+
*
|
|
28
|
+
* O caso perigoso é o INVERSO e é silencioso: numa reavaliação que BAIXA a nota
|
|
29
|
+
* (o #93 caiu de 8.9 para 8.3 quando uma correção abriu um bloqueante), o gate
|
|
30
|
+
* leria a nota antiga, mais alta, e AUTO-PASSARIA o Gate 3 sobre um produto com
|
|
31
|
+
* bloqueante aberto — a mesma classe de defeito que a v8.26.0 existiu para
|
|
32
|
+
* fechar, voltando por outra porta: lendo um veredito real, porém vencido.
|
|
33
|
+
*
|
|
34
|
+
* DECISÃO EXPLÍCITA — "o último vence", e não "múltiplos tokens viram
|
|
35
|
+
* `report-ambiguous` e recusam":
|
|
36
|
+
*
|
|
37
|
+
* 1. É a semântica do próprio artefato. Append-only significa que o arquivo é
|
|
38
|
+
* um LOG, e o valor corrente de um log é a sua última entrada. Ler o
|
|
39
|
+
* primeiro não é uma política conservadora — é ler a entrada errada.
|
|
40
|
+
* 2. Recusar transformaria um veredito REAL e CORRENTE numa pausa que só sai
|
|
41
|
+
* editando à mão um arquivo declarado append-only. Isto é exatamente o
|
|
42
|
+
* contorno manual que este conserto existe para eliminar, promovido a
|
|
43
|
+
* requisito.
|
|
44
|
+
* 3. Recusar não é mais seguro em nenhum dos dois casos observados: com a nota
|
|
45
|
+
* SUBINDO, o humano é obrigado a mexer no relatório para liberar um gate
|
|
46
|
+
* que já foi aprovado; com a nota CAINDO, "o último vence" já pausa sozinho
|
|
47
|
+
* pela regra de score, que é a razão certa a reportar.
|
|
48
|
+
*
|
|
49
|
+
* Ambiguidade não fica silenciosa, ainda assim: `evaluatorReportState` devolve
|
|
50
|
+
* `scoreTokens` (quantos tokens vivos o arquivo tem) e `superseded` (os valores
|
|
51
|
+
* anteriores, na ordem do arquivo). Quem consome pode dizer "9.1, terceira
|
|
52
|
+
* rodada, superando 8.9 e 8.3" em vez de fingir que só havia um veredito.
|
|
18
53
|
*/
|
|
19
54
|
|
|
20
55
|
import { existsSync, readFileSync } from 'fs';
|
|
@@ -27,29 +62,133 @@ import { getAbsoluteOutputPath } from '../core/paths/output-schema.js';
|
|
|
27
62
|
*/
|
|
28
63
|
export const COMPOSITE_SCORE_TOKEN = '**Composite-Score:**';
|
|
29
64
|
|
|
30
|
-
|
|
65
|
+
/**
|
|
66
|
+
* O token das rubricas de PROVA (`.morph/framework/evals/proof-rubrics/`):
|
|
67
|
+
* `**Proof-Scores:** mutation=9 verde=8 fiacao=9 guard=7 eval=8`. Mesma convenção
|
|
68
|
+
* literal do Composite-Score de propósito — mesmo arquivo, mesmo módulo leitor,
|
|
69
|
+
* mesmo estilo de token. Ele pontua a EVIDÊNCIA que o avaliador produziu, nunca
|
|
70
|
+
* o produto: não entra no composto, impõe teto em `test-coverage`.
|
|
71
|
+
*/
|
|
72
|
+
export const PROOF_SCORES_TOKEN = '**Proof-Scores:**';
|
|
73
|
+
|
|
74
|
+
/** `g` é obrigatório: o arquivo é append-only e o token vigente é o ÚLTIMO. */
|
|
75
|
+
const COMPOSITE_SCORE_RE = /\*\*Composite-Score:\*\*\s*([0-9]+(?:\.[0-9]+)?)/g;
|
|
76
|
+
|
|
77
|
+
/** Idem — uma reavaliação reescreve os Proof-Scores acrescentando ao fim. */
|
|
78
|
+
const PROOF_SCORES_RE = /\*\*Proof-Scores:\*\*[ \t]*([^\r\n]*)/g;
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* A seção de prova de mutação. Exige `##`: um `# Mutações` é outra estrutura
|
|
82
|
+
* (H1 é título de documento, não seção), e o template que a `morph-review`
|
|
83
|
+
* entrega ao avaliador gera exatamente `## Mutações`. Aceita a grafia sem
|
|
84
|
+
* acento porque um relatório escrito em terminal ASCII continua sendo o mesmo
|
|
85
|
+
* fato — o que não se aceita é o nível errado de cabeçalho.
|
|
86
|
+
*/
|
|
87
|
+
const MUTATION_SECTION_RE = /^##\s+Muta[çc][õo]es\s*$/m;
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* A seção de prova de MÍDIA. Mesma disciplina do `## Mutações`: exige `##`, e
|
|
91
|
+
* aceita a grafia sem acento porque um relatório escrito em terminal ASCII
|
|
92
|
+
* continua sendo o mesmo fato. `Mídia gerada` / `Midia gerada`.
|
|
93
|
+
*/
|
|
94
|
+
const MEDIA_SECTION_RE = /^##\s+M[íi]dia\s+gerada\s*$/m;
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* As chaves reconhecidas de `**Proof-Scores:**`, uma por rubrica de prova.
|
|
98
|
+
* Chave fora desta lista é IGNORADA (não vira score, não vira erro): o relatório
|
|
99
|
+
* é texto de LLM e uma chave inventada não deve nem contaminar nenhum mínimo nem
|
|
100
|
+
* derrubar a leitura das outras.
|
|
101
|
+
*
|
|
102
|
+
* `media` PRECISA estar aqui. Sem isso a rubrica `media-claims.md` seria
|
|
103
|
+
* decorativa: o avaliador escreveria `media=7` e o número seria descartado em
|
|
104
|
+
* silêncio, que é o caso "campo publicado sem nenhum leitor".
|
|
105
|
+
*/
|
|
106
|
+
export const PROOF_SCORE_KEYS = ['mutation', 'verde', 'fiacao', 'guard', 'eval', 'media', 'obs'];
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* As chaves que NÃO entram no `min` de `test-coverage` porque impõem teto em
|
|
110
|
+
* OUTRA dimensão: `media` (teto em `architecture`) e `obs` (teto em
|
|
111
|
+
* `code-quality`).
|
|
112
|
+
*
|
|
113
|
+
* **`obs` chegou exatamente pelo caminho que o parágrafo abaixo antecipou**, e
|
|
114
|
+
* vale registrar porque o aviso não bastou. A feature irmã (#94) criou a rubrica
|
|
115
|
+
* `observabilidade-genai.md`, escreveu `obs=` onze vezes no seu próprio
|
|
116
|
+
* `evaluator-report.md` — e a chave não estava em `PROOF_SCORE_KEYS`, nem lá nem
|
|
117
|
+
* na base dela. O parser a descartava em silêncio (ver o `continue` de
|
|
118
|
+
* `parseProofScores`), então a rubrica nasceu DECORATIVA e atravessou **onze
|
|
119
|
+
* rodadas de Gate 3** sem que ninguém percebesse: o número era escrito, lido por
|
|
120
|
+
* um humano no relatório, e nunca chegava ao gate. Só o rebase, que põe as duas
|
|
121
|
+
* features na mesma árvore, tornou o buraco visível.
|
|
122
|
+
*
|
|
123
|
+
* **Isto é uma exclusão, e a forma importa mais que a lista.** A primeira versão
|
|
124
|
+
* era o inverso — uma lista fechada das quatro chaves que entram. Ela responde
|
|
125
|
+
* certo hoje e erra sozinha amanhã: a feature irmã acrescenta uma quinta chave
|
|
126
|
+
* (`eval`) com rubrica própria, e depois do rebase esse `eval=N` cairia do teto
|
|
127
|
+
* **em silêncio** — o "campo publicado sem nenhum leitor" que este mesmo arquivo
|
|
128
|
+
* existe para impedir, produzido pela correção.
|
|
129
|
+
*
|
|
130
|
+
* Por exclusão, uma chave nova nasce DENTRO do mínimo por padrão, e tirá-la de lá
|
|
131
|
+
* passa a ser um ato deliberado e visível: uma linha aqui, com a dimensão que ela
|
|
132
|
+
* limita escrita ao lado. Errar para o lado de "conta no mínimo" custa um teto a
|
|
133
|
+
* mais; errar para o outro lado devolve o gate cego.
|
|
134
|
+
*
|
|
135
|
+
* O motivo de `media` estar fora continua o mesmo: as quatro do mínimo perguntam
|
|
136
|
+
* "a evidência é real?"; `media` pergunta "a chamada mora no lugar certo? que
|
|
137
|
+
* estados existem? o que é publicado?". Um `media=4` derrubando o teto de TESTE
|
|
138
|
+
* seriam dois fatos diferentes lidos como um só.
|
|
139
|
+
*/
|
|
140
|
+
export const NON_MUTATION_PROOF_KEYS = ['media', 'obs'];
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* As chaves que entram no `min` que impõe teto em `test-coverage`: DERIVADA de
|
|
144
|
+
* {@link PROOF_SCORE_KEYS} menos {@link NON_MUTATION_PROOF_KEYS} — nunca digitada.
|
|
145
|
+
* Ver o racional da exclusão acima.
|
|
146
|
+
*/
|
|
147
|
+
export const MUTATION_PROOF_KEYS =
|
|
148
|
+
PROOF_SCORE_KEYS.filter((k) => !NON_MUTATION_PROOF_KEYS.includes(k));
|
|
31
149
|
|
|
32
150
|
/** Path canônico do evaluator-report da feature. Fonte única para os dois comandos. */
|
|
33
151
|
export function evaluatorReportPath(cwd, featureName) {
|
|
34
152
|
return getAbsoluteOutputPath(cwd, featureName, 'evaluatorReport');
|
|
35
153
|
}
|
|
36
154
|
|
|
155
|
+
/** Conteúdo do relatório, ou null quando ausente/ilegível. Nunca lança. */
|
|
156
|
+
function readReport(cwd, featureName) {
|
|
157
|
+
try {
|
|
158
|
+
const p = evaluatorReportPath(cwd, featureName);
|
|
159
|
+
if (!existsSync(p)) return null;
|
|
160
|
+
return readFileSync(p, 'utf8');
|
|
161
|
+
} catch {
|
|
162
|
+
return null;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Todos os valores de `**Composite-Score:**` do arquivo, NA ORDEM DO ARQUIVO.
|
|
168
|
+
* O último é o vigente; os anteriores são rodadas superadas.
|
|
169
|
+
*
|
|
170
|
+
* @param {string} text
|
|
171
|
+
* @returns {number[]}
|
|
172
|
+
*/
|
|
173
|
+
function compositeScoresIn(text) {
|
|
174
|
+
return [...text.matchAll(COMPOSITE_SCORE_RE)].map((m) => Number(m[1]));
|
|
175
|
+
}
|
|
176
|
+
|
|
37
177
|
/**
|
|
38
178
|
* Score composto REAL da feature, do token gravado pelo avaliador independente.
|
|
39
179
|
*
|
|
180
|
+
* Num relatório reavaliado (append-only), é o token do FIM — o veredito
|
|
181
|
+
* vigente. Ver o bloco "O TOKEN VIGENTE É O ÚLTIMO" no topo do arquivo.
|
|
182
|
+
*
|
|
40
183
|
* @returns {number|undefined} undefined quando o relatório não existe, não é
|
|
41
184
|
* legível, ou existe sem o token (relatório legado ou oco). `undefined` é
|
|
42
185
|
* deliberado e não 0: quem chama distingue "sem veredito" de "veredito ruim".
|
|
43
186
|
*/
|
|
44
187
|
export function evaluatorCompositeScore(cwd, featureName) {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
return m ? Number(m[1]) : undefined;
|
|
50
|
-
} catch {
|
|
51
|
-
return undefined;
|
|
52
|
-
}
|
|
188
|
+
const text = readReport(cwd, featureName);
|
|
189
|
+
if (text === null) return undefined;
|
|
190
|
+
const scores = compositeScoresIn(text);
|
|
191
|
+
return scores.length === 0 ? undefined : scores[scores.length - 1];
|
|
53
192
|
}
|
|
54
193
|
|
|
55
194
|
/**
|
|
@@ -60,13 +199,128 @@ export function evaluatorCompositeScore(cwd, featureName) {
|
|
|
60
199
|
* "o avaliador rodou mas o relatório está oco — ele não seguiu o contrato";
|
|
61
200
|
* e só o terceiro caso é aprovável.
|
|
62
201
|
*
|
|
63
|
-
*
|
|
202
|
+
* `scoreTokens`/`superseded` só aparecem no caso `ok` e existem para que uma
|
|
203
|
+
* reavaliação nunca passe silenciosa: o score é o último, mas quem consome sabe
|
|
204
|
+
* quantas rodadas o arquivo carrega e quais notas foram superadas.
|
|
205
|
+
*
|
|
206
|
+
* @returns {{ status: 'ok'|'missing'|'untokenized', score?: number,
|
|
207
|
+
* scoreTokens?: number, superseded?: number[], path: string }}
|
|
64
208
|
*/
|
|
65
209
|
export function evaluatorReportState(cwd, featureName) {
|
|
66
210
|
const path = evaluatorReportPath(cwd, featureName);
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
211
|
+
const text = readReport(cwd, featureName);
|
|
212
|
+
if (text === null) return { status: 'missing', path };
|
|
213
|
+
const scores = compositeScoresIn(text);
|
|
214
|
+
if (scores.length === 0) return { status: 'untokenized', path };
|
|
215
|
+
return {
|
|
216
|
+
status: 'ok',
|
|
217
|
+
score: scores[scores.length - 1],
|
|
218
|
+
scoreTokens: scores.length,
|
|
219
|
+
superseded: scores.slice(0, -1),
|
|
220
|
+
path,
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* Parseia o corpo de UMA linha `**Proof-Scores:**` — pares `chave=N` separados
|
|
226
|
+
* por espaço.
|
|
227
|
+
*
|
|
228
|
+
* @param {string} body
|
|
229
|
+
* @returns {Record<string, number>|undefined} undefined quando nenhum par
|
|
230
|
+
* VÁLIDO foi lido (linha vazia, só chaves desconhecidas, ou só valores
|
|
231
|
+
* não-numéricos). `undefined` e não `{}` pela mesma disciplina do
|
|
232
|
+
* `evaluatorCompositeScore`: "sem veredito" tem de ser distinguível de
|
|
233
|
+
* "veredito vazio".
|
|
234
|
+
*/
|
|
235
|
+
function parseProofScores(body) {
|
|
236
|
+
const out = {};
|
|
237
|
+
for (const m of body.matchAll(/([A-Za-zÀ-ÿ][\w-]*)\s*=\s*([^\s]+)/g)) {
|
|
238
|
+
const key = m[1].toLowerCase();
|
|
239
|
+
if (!PROOF_SCORE_KEYS.includes(key)) continue;
|
|
240
|
+
if (!/^[0-9]+(?:\.[0-9]+)?$/.test(m[2])) continue;
|
|
241
|
+
out[key] = Number(m[2]);
|
|
242
|
+
}
|
|
243
|
+
return Object.keys(out).length === 0 ? undefined : out;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* Estado de PROVA do relatório: a seção `## Mutações` está lá, e quais
|
|
248
|
+
* Proof-Scores o avaliador registrou.
|
|
249
|
+
*
|
|
250
|
+
* Deriva do disco e não julga: quem decide se a ausência pausa o Gate 3 é
|
|
251
|
+
* `risk-detector.js` (a divisão "gate-check coleta, risk-detector decide"), e
|
|
252
|
+
* quem decide o teto é a rubrica `test-coverage.md`. O `min` NÃO é gravado
|
|
253
|
+
* aqui — é derivado por quem consome, para que exista um só lugar onde
|
|
254
|
+
* "mínimo de quantas chaves" é definido.
|
|
255
|
+
*
|
|
256
|
+
* Arquivo ausente ou ilegível: `{ mutationSection: false, mediaSection: false,
|
|
257
|
+
* proofScores: undefined }`. Nunca lança, e nunca devolve `0` no lugar de
|
|
258
|
+
* `undefined`.
|
|
259
|
+
*
|
|
260
|
+
* `mediaSection` é lido do MESMO arquivo pelo MESMO módulo, de propósito: uma
|
|
261
|
+
* segunda leitura do relatório noutro lugar é como duas superfícies passam a
|
|
262
|
+
* discordar sobre o que ele diz.
|
|
263
|
+
*
|
|
264
|
+
* @param {string} cwd
|
|
265
|
+
* @param {string} featureName
|
|
266
|
+
* @returns {{ mutationSection: boolean, mediaSection: boolean, proofScores: Record<string, number>|undefined, path: string }}
|
|
267
|
+
*/
|
|
268
|
+
export function evaluatorProofState(cwd, featureName) {
|
|
269
|
+
const path = evaluatorReportPath(cwd, featureName);
|
|
270
|
+
const text = readReport(cwd, featureName);
|
|
271
|
+
if (text === null) {
|
|
272
|
+
return { mutationSection: false, mediaSection: false, proofScores: undefined, path };
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
// Append-only outra vez: numa reavaliação a linha nova vai para o fim, e é
|
|
276
|
+
// ela que vale. A primeira linha descreveria a prova de uma rodada superada.
|
|
277
|
+
const lines = [...text.matchAll(PROOF_SCORES_RE)];
|
|
278
|
+
const proofScores = lines.length === 0
|
|
279
|
+
? undefined
|
|
280
|
+
: parseProofScores(lines[lines.length - 1][1]);
|
|
281
|
+
|
|
282
|
+
return {
|
|
283
|
+
mutationSection: MUTATION_SECTION_RE.test(text),
|
|
284
|
+
mediaSection: MEDIA_SECTION_RE.test(text),
|
|
285
|
+
proofScores,
|
|
286
|
+
path,
|
|
287
|
+
};
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
/**
|
|
291
|
+
* O menor Proof-Score das provas de EVIDÊNCIA — o que impõe o teto em
|
|
292
|
+
* `test-coverage`.
|
|
293
|
+
*
|
|
294
|
+
* Calculado sobre {@link MUTATION_PROOF_KEYS} — que é
|
|
295
|
+
* {@link PROOF_SCORE_KEYS} MENOS {@link NON_MUTATION_PROOF_KEYS}, e não uma lista
|
|
296
|
+
* digitada. `media` responde a outra pergunta e limita outra dimensão
|
|
297
|
+
* (`architecture`); ler as duas famílias como um mínimo só faria um `media=4`
|
|
298
|
+
* derrubar o teto de teste sem que nada de teste tivesse acontecido. Uma chave
|
|
299
|
+
* NOVA de prova entra aqui sozinha: excluí-la exige uma linha deliberada em
|
|
300
|
+
* `NON_MUTATION_PROOF_KEYS`, e nunca acontece por esquecimento.
|
|
301
|
+
*
|
|
302
|
+
* @param {Record<string, number>|undefined} proofScores
|
|
303
|
+
* @returns {number|null} null quando não há nenhum score do mínimo: SEM TETO A
|
|
304
|
+
* APLICAR, jamais "teto 0". A mesma razão pela qual `count: null` do verify
|
|
305
|
+
* não é 0.
|
|
306
|
+
*/
|
|
307
|
+
export function minProofScore(proofScores) {
|
|
308
|
+
if (!proofScores) return null;
|
|
309
|
+
const values = MUTATION_PROOF_KEYS
|
|
310
|
+
.map((key) => proofScores[key])
|
|
311
|
+
.filter((n) => typeof n === 'number' && Number.isFinite(n));
|
|
312
|
+
return values.length === 0 ? null : Math.min(...values);
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
/**
|
|
316
|
+
* O Proof-Score de MÍDIA, lido à parte. Impõe teto em `architecture` (tabela em
|
|
317
|
+
* `framework/evals/rubrics/architecture.md`, "Tetos de prova de mídia").
|
|
318
|
+
*
|
|
319
|
+
* @param {Record<string, number>|undefined} proofScores
|
|
320
|
+
* @returns {number|null} null quando a chave não foi registrada — o caso normal
|
|
321
|
+
* de uma feature que não gera mídia, e nunca "teto 0".
|
|
322
|
+
*/
|
|
323
|
+
export function mediaProofScore(proofScores) {
|
|
324
|
+
const value = proofScores?.media;
|
|
325
|
+
return typeof value === 'number' && Number.isFinite(value) ? value : null;
|
|
72
326
|
}
|