@polymorphism-tech/morph-spec 8.34.2 → 8.35.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CLAUDE.md +20 -3
- package/README.md +2 -2
- package/bin/morph-spec.js +18 -4
- package/bin/validate.js +379 -379
- package/claude-plugin.json +1 -1
- package/docs/CHEATSHEET.md +5 -4
- package/docs/QUICKSTART.md +1 -1
- package/framework/MORPH.md +16 -17
- package/framework/agents.json +197 -44
- package/framework/ai-pin.json +22 -0
- package/framework/commands/morph-media.md +45 -0
- package/framework/docs/CLI.md +234 -9
- package/framework/evals/proof-rubrics/README.md +76 -0
- package/framework/evals/proof-rubrics/eval-de-modelo.md +64 -0
- package/framework/evals/proof-rubrics/fiacao.md +54 -0
- package/framework/evals/proof-rubrics/guard-cego.md +52 -0
- package/framework/evals/proof-rubrics/media-claims.md +109 -0
- package/framework/evals/proof-rubrics/mutation-proof.md +77 -0
- package/framework/evals/proof-rubrics/observabilidade-genai.md +119 -0
- package/framework/evals/proof-rubrics/verde-nao-e-coberto.md +48 -0
- package/framework/evals/rubrics/architecture.md +30 -0
- package/framework/evals/rubrics/code-quality.md +26 -0
- package/framework/evals/rubrics/test-coverage.md +20 -0
- package/framework/hooks/claude-code/core/protect-spec-files.js +41 -4
- package/framework/hooks/claude-code/statusline.sh +11 -11
- package/framework/hooks/git/commit-msg/conventional-commits.sh +33 -33
- package/framework/hooks/git/pre-commit/agents.sh +25 -25
- package/framework/hooks/git/pre-commit/orchestrator.sh +64 -64
- package/framework/hooks/git/pre-commit/specs.sh +50 -50
- package/framework/hooks/git/pre-push/run-tests.sh +44 -44
- package/framework/hooks/shared/e2e-check.js +135 -22
- package/framework/hooks/shared/stdin-reader.js +26 -26
- package/framework/rules/ai-agents-standards.md +14 -2
- package/framework/schemas/ai-pin.schema.json +97 -0
- package/framework/schemas/config.schema.json +107 -0
- package/framework/schemas/feature.schema.json +23 -4
- package/framework/skills/core/create-umbraco-lp/SKILL.md +1 -1
- package/framework/skills/core/migrate-lp-to-umbraco/SKILL.md +1 -1
- package/framework/skills/core/morph-apply/SKILL.md +26 -5
- package/framework/skills/core/morph-brainstorming/SKILL.md +1 -1
- package/framework/skills/core/morph-eval/SKILL.md +1 -1
- package/framework/skills/core/morph-hotfix/SKILL.md +2 -2
- package/framework/skills/core/morph-implement/SKILL.md +18 -2
- package/framework/skills/core/morph-media/SKILL.md +215 -0
- package/framework/skills/core/morph-plan/SKILL.md +33 -2
- package/framework/skills/core/morph-proposal/SKILL.md +1 -1
- package/framework/skills/core/morph-review/SKILL.md +166 -9
- package/framework/skills/core/morph-stack-scan/SKILL.md +1 -1
- package/framework/skills/core/morph-standards/SKILL.md +1 -1
- package/framework/skills/core/morph-uiux/SKILL.md +1 -1
- package/framework/standards/PROVENANCE.json +81 -3
- package/framework/standards/STANDARDS.json +1483 -839
- package/framework/standards/ai-agents/agent-archetypes.md +160 -0
- package/framework/standards/ai-agents/agent-session.md +164 -68
- package/framework/standards/ai-agents/agent-spec.md +196 -0
- package/framework/standards/ai-agents/batching.md +61 -37
- package/framework/standards/ai-agents/context-providers.md +97 -24
- package/framework/standards/ai-agents/conversational-agent-with-phases.md +239 -0
- package/framework/standards/ai-agents/cost-and-budget.md +256 -0
- package/framework/standards/ai-agents/durable-workflows-hitl.md +98 -5
- package/framework/standards/ai-agents/evals-with-cache.md +289 -0
- package/framework/standards/ai-agents/guardrails.md +222 -0
- package/framework/standards/ai-agents/llm-runtime-defaults.md +226 -0
- package/framework/standards/ai-agents/mcp-server.md +119 -18
- package/framework/standards/ai-agents/mcp-tools.md +85 -32
- package/framework/standards/ai-agents/media-pipeline.md +352 -0
- package/framework/standards/ai-agents/media-video.md +267 -0
- package/framework/standards/ai-agents/middleware-patterns.md +39 -5
- package/framework/standards/ai-agents/modalities-image-gen.md +354 -105
- package/framework/standards/ai-agents/modalities-speech-to-text.md +8 -2
- package/framework/standards/ai-agents/modalities-text-to-speech.md +10 -2
- package/framework/standards/ai-agents/modalities-vision.md +6 -2
- package/framework/standards/ai-agents/multi-agent-patterns.md +61 -5
- package/framework/standards/ai-agents/observability-patterns.md +227 -17
- package/framework/standards/ai-agents/production.md +38 -9
- package/framework/standards/ai-agents/prompt-sources.md +389 -0
- package/framework/standards/ai-agents/providers/model-registry.md +174 -39
- package/framework/standards/ai-agents/rag-custom-pgvector.md +69 -4
- package/framework/standards/ai-agents/service-tier-flex.md +27 -19
- package/framework/standards/ai-agents/setup.md +166 -50
- package/framework/standards/ai-agents/structured-output.md +34 -3
- package/framework/standards/ai-agents/sweet-spot.md +23 -3
- package/framework/standards/ai-agents/testing-ai.md +236 -0
- package/framework/standards/ai-agents/vector-data-extensions.md +50 -20
- package/framework/standards/ai-agents/workflows.md +27 -7
- package/framework/standards/frontend/design-system/ai-image-generation.md +12 -0
- package/framework/standards/frontend/design-system/ai-video-generation.md +13 -0
- package/framework/standards/infrastructure/docker/local-compose-isolation.md +3 -1
- package/framework/templates/.idea/morph-templates.xml +92 -0
- package/framework/templates/.vscode/morph-templates.code-snippets +186 -0
- package/framework/templates/IDE-SNIPPETS.md +262 -262
- package/framework/templates/REGISTRY.json +13 -0
- package/framework/templates/code/dotnet/abstractions/api-endpoint.cs +7 -7
- package/framework/templates/code/dotnet/ai-agents/AgentBootstrap.cs.template +39 -39
- package/framework/templates/code/dotnet/ai-agents/EmbeddingService.cs.template +68 -68
- package/framework/templates/code/dotnet/ai-agents/ModelRegistry.cs.template +117 -117
- package/framework/templates/code/dotnet/ai-agents/PromptRepository.cs.template +1 -1
- package/framework/templates/code/dotnet/ai-agents/ResilientToolMiddleware.cs.template +61 -61
- package/framework/templates/code/dotnet/ai-agents/VectorSearchTool.cs.template +107 -107
- package/framework/templates/code/dotnet/ai-agents/model-registry.json.template +58 -58
- package/framework/templates/code/dotnet/contracts/contracts-vsa.cs +281 -281
- package/framework/templates/code/dotnet/database/migration.cs +83 -83
- package/framework/templates/code/dotnet/feature/endpoint.cs.hbs +21 -21
- package/framework/templates/code/dotnet/feature/request.cs.hbs +4 -4
- package/framework/templates/code/dotnet/feature/response.cs.hbs +4 -4
- package/framework/templates/code/dotnet/feature/validator.cs.hbs +15 -15
- package/framework/templates/code/sql/ai-agents/agent-prompts-migration.sql.template +1 -1
- package/framework/templates/code/sql/ai-agents/pgvector-embeddings-migration.sql.template +91 -91
- package/framework/templates/code/typescript/contracts.ts +167 -167
- package/framework/templates/docs/clarifications.md +253 -253
- package/framework/templates/docs/schema-analysis.md +119 -119
- package/framework/templates/docs/ui-components.md +52 -52
- package/framework/templates/docs/ui-design-system.md +76 -76
- package/framework/templates/docs/ui-flows.md +167 -167
- package/framework/templates/docs/ui-mockups.md +98 -98
- package/framework/templates/dotnet/ai-kit/Directory.Build.props +25 -0
- package/framework/templates/dotnet/ai-kit/Directory.Packages.props +26 -0
- package/framework/templates/dotnet/ai-kit/Morph.AiKit.sln +56 -0
- package/framework/templates/dotnet/ai-kit/NuGet.config +12 -0
- package/framework/templates/dotnet/ai-kit/README.md +128 -0
- package/framework/templates/dotnet/ai-kit/global.json +9 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Agents/AgentApi.cs +65 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Agents/AgentFactory.cs +289 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Agents/AgentFactoryOptions.cs +91 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Agents/AgentSpec.cs +91 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Agents/AgentSpecOptions.cs +181 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/AiKitAssemblyMarker.cs +14 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Conversation/ConversationStore.cs +174 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Conversation/IConversationStore.cs +54 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Conversation/InMemoryConversationStore.cs +75 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Evals/CountingChatClient.cs +71 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Evals/EvalAssertion.cs +246 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Evals/EvalCacheMissException.cs +57 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Evals/EvalCacheOptions.cs +78 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Evals/EvalCacheStamp.cs +225 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Evals/EvalFixture.cs +463 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Evals/EvalMode.cs +32 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Evals/EvalQualityEvaluators.cs +49 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Evals/EvalScenario.cs +214 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Evals/EvalSummary.cs +168 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Evals/OfflineChatClient.cs +142 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Evals/ShortPathResponseCache.cs +349 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/IMediaGenerator.cs +42 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/IMediaProvider.cs +77 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/MediaArtifact.cs +28 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/MediaDisclosure.cs +107 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/MediaGenerator.cs +253 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/MediaIdempotencyKey.cs +103 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/MediaJob.cs +259 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/MediaJobId.cs +21 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/MediaJobState.cs +47 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/MediaPricing.cs +102 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/MediaProvenance.cs +44 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/MediaRequest.cs +192 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/MediaResult.cs +94 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/MediaReview.cs +99 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/MediaSeams.cs +97 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/MediaStore.cs +133 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/MorphMedia.cs +93 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/Providers/GoogleImageProvider.cs +112 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/Providers/OpenAIImageProvider.cs +288 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Media/Providers/VeoVideoProvider.cs +158 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Middleware/IUsageCostSink.cs +29 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Middleware/UsageCostMiddleware.cs +208 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Middleware/UsageCostRecord.cs +95 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Morph.AiKit.csproj +38 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Observability/MorphOpenTelemetryExtensions.cs +119 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Observability/MorphTelemetryOptions.cs +82 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Providers/IProviderClientFactory.cs +33 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Providers/ModelAlias.cs +267 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Providers/ModelRegistry.cs +474 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Providers/model-registry.v2.json +87 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Rag/DeltaIngest.cs +169 -0
- package/framework/templates/dotnet/ai-kit/src/Morph.AiKit/Rag/DeltaPlan.cs +49 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/AgentFactoryTests.cs +495 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/AgentSpecTests.cs +260 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/ConversationStoreTests.cs +405 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/DeltaIngestTests.cs +379 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Evals/EvalAssertionTests.cs +197 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Evals/EvalCacheMissTests.cs +139 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Evals/EvalCacheStampTests.cs +157 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Evals/EvalFailuresTests.cs +178 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Evals/EvalFixtureTests.cs +153 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Evals/EvalRefreshTests.cs +194 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Evals/EvalWorkspace.cs +86 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Evals/KitEvals.cs +213 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Evals/OfflineChatClientTests.cs +95 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Fakes/FakeChatClient.cs +225 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Fakes/FakeChatClientTests.cs +215 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Fakes/FakeClock.cs +33 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Fakes/FakeMediaProvider.cs +89 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Fakes/FakeProviderClientFactory.cs +55 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Fakes/FakeUsageCostSink.cs +60 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Fakes/InMemoryMediaStore.cs +131 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/MediaAccessibilityTests.cs +133 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/MediaAliasIsNotAnAgentTests.cs +127 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/MediaDisclosureTests.cs +216 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/MediaGeneratorTests.cs +264 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/MediaIdempotencyKeyTests.cs +148 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/MediaJobStateTests.cs +184 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/MediaReviewTests.cs +89 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/MediaStoreTests.cs +98 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/ModelRegistryTests.cs +451 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/Morph.AiKit.Tests.csproj +76 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/SkeletonSmokeTests.cs +33 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/TelemetryTests.cs +261 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/UsageCostMiddlewareTests.cs +374 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/eval-cache/.morph-eval-cache.json +12 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/eval-cache/cache/orcamento.acme.a-resposta-estruturada/1/CF70A7CE27BBD66A/contents.data +13 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/eval-cache/cache/orcamento.acme.a-resposta-estruturada/1/CF70A7CE27BBD66A/entry.json +7 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/eval-cache/cache/triagem.acme.a-saudacao/1/19F631228C6E00BA/contents.data +13 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/eval-cache/cache/triagem.acme.a-saudacao/1/19F631228C6E00BA/entry.json +7 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/eval-cache/cache/triagem.acme.b-escalonamento/1/A24A7C9BDD8239D8/contents.data +13 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/eval-cache/cache/triagem.acme.b-escalonamento/1/A24A7C9BDD8239D8/entry.json +7 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/eval-cache/cache/triagem.globex.a-saudacao/1/E38CD37DF003EDB7/contents.data +13 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/eval-cache/cache/triagem.globex.a-saudacao/1/E38CD37DF003EDB7/entry.json +7 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/eval-datasets/orcamento/acme/a-resposta-estruturada.json +24 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/eval-datasets/triagem/acme/a-saudacao.json +23 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/eval-datasets/triagem/acme/b-escalonamento.json +24 -0
- package/framework/templates/dotnet/ai-kit/tests/Morph.AiKit.Tests/eval-datasets/triagem/globex/a-saudacao.json +23 -0
- package/framework/templates/feature/decisions.md +122 -122
- package/framework/templates/frontend/nextjs/Dockerfile.nextjs.hbs +43 -43
- package/framework/templates/frontend/nextjs/client-component.tsx.hbs +26 -26
- package/framework/templates/frontend/nextjs/env.mjs.hbs +32 -32
- package/framework/templates/frontend/nextjs/feature-form.tsx.hbs +56 -56
- package/framework/templates/frontend/nextjs/page.tsx.hbs +22 -22
- package/framework/templates/frontend/nextjs/tsconfig.json.hbs +26 -26
- package/framework/templates/frontend/nextjs/use-feature.ts.hbs +54 -54
- package/framework/templates/infrastructure/docker/Dockerfile.template +58 -58
- package/framework/templates/infrastructure/docker/dockerfile-api.dockerfile +38 -38
- package/framework/templates/infrastructure/docker/dockerfile-web.dockerfile +48 -48
- package/framework/templates/infrastructure/github/README.md +56 -56
- package/framework/templates/infrastructure/github/actions/docker-build-push/action.yml.hbs +45 -45
- package/framework/templates/infrastructure/github/actions/health-check/action.yml.hbs +27 -27
- package/framework/templates/infrastructure/github/workflows/docker-build-push.yml.hbs +59 -59
- package/framework/templates/infrastructure/github/workflows/dotnet-build.yml.hbs +39 -39
- package/framework/templates/integrations/asaas-client.cs +387 -387
- package/framework/templates/integrations/asaas-webhook.cs +351 -351
- package/framework/templates/meta-prompts/fusion/fusion-agent.md +76 -76
- package/framework/templates/meta-prompts/fusion/fusion-aggregator.md +100 -100
- package/framework/templates/meta-prompts/validators/pre-commit-validator.md +95 -95
- package/framework/templates/project/validate.js +120 -120
- package/framework/templates/state.template.json +17 -17
- package/framework/templates/ui/design-system.css +226 -226
- package/package.json +3 -3
- package/src/commands/dashboard/dashboard.js +53 -53
- package/src/commands/e2e/e2e.js +15 -2
- package/src/commands/index.js +13 -13
- package/src/commands/project/checkpoint.js +209 -209
- package/src/commands/project/doctor.js +140 -5
- package/src/commands/project/update.js +469 -153
- package/src/commands/project/worktree.js +8 -1
- package/src/commands/state/advance.js +24 -2
- package/src/commands/state/approve.js +33 -1
- package/src/commands/state/create.js +72 -11
- package/src/commands/state/finish.js +333 -21
- package/src/commands/state/gate-check.js +190 -6
- package/src/commands/state/score.js +36 -1
- package/src/commands/validation/verify.js +134 -25
- package/src/core/state/phase-state-machine.js +197 -197
- package/src/core/state/state-manager.js +9 -1
- package/src/core/templates/template-renderer.js +477 -477
- package/src/dashboard/app/components/DetailPanel.jsx +11 -11
- package/src/dashboard/app/components/FlowGraph.jsx +17 -17
- package/src/dashboard/app/components/SearchFilter.jsx +22 -22
- package/src/dashboard/app/hooks/useDetailPanel.js +15 -15
- package/src/dashboard/app/main.jsx +13 -13
- package/src/dashboard/app/pages/AgentMap.jsx +370 -370
- package/src/dashboard/app/pages/PhasePipeline.jsx +408 -408
- package/src/dashboard/app/pages/RulesMap.jsx +273 -273
- package/src/dashboard/app/pages/SkillsLibrary.jsx +366 -366
- package/src/dashboard/app/pages/Standards.jsx +332 -332
- package/src/dashboard/app/styles/index.css +47 -47
- package/src/dashboard/index.html +12 -12
- package/src/dashboard/package.json +24 -24
- package/src/dashboard/scanner/phases-scanner.js +15 -15
- package/src/dashboard/scanner/rubrics-scanner.js +12 -12
- package/src/dashboard/scanner/rules-scanner.js +37 -37
- package/src/dashboard/scanner/skills-scanner.js +43 -43
- package/src/dashboard/scanner/squads-scanner.js +13 -13
- package/src/dashboard/vite-plugin-morph-data.js +17 -17
- package/src/dashboard/vite.config.js +24 -24
- package/src/lib/ai/ai-checks.js +182 -0
- package/src/lib/ai/ai-project-scan.js +347 -0
- package/src/lib/ai/code-audit.js +181 -0
- package/src/lib/ai/comment-stripper.js +184 -0
- package/src/lib/ai/pin-drift.js +138 -0
- package/src/lib/ai/registry-audit.js +285 -0
- package/src/lib/detectors/design-system-detector.js +188 -188
- package/src/lib/detectors/index.js +217 -217
- package/src/lib/e2e/compose-env.js +50 -4
- package/src/lib/evaluator-report.js +269 -15
- package/src/lib/generators/design-system-generator.js +508 -508
- package/src/lib/generators/settings-generator.js +209 -209
- package/src/lib/git/default-branch.js +92 -4
- package/src/lib/hooks/hook-executor.js +167 -167
- package/src/lib/installers/effects.js +193 -0
- package/src/lib/installers/mcp-installer.js +719 -719
- package/src/lib/installers/templates-reconcile.js +3 -3
- package/src/lib/risk-detector.js +284 -0
- package/src/lib/standards/verified-against.js +276 -0
- package/src/lib/tasks/eval-node.js +485 -0
- package/src/lib/tasks/linux-runner.js +297 -0
- package/src/lib/tasks/task-classifier.js +30 -30
- package/src/lib/tasks/task-parser.js +209 -209
- package/src/lib/tasks/test-nodes.js +486 -0
- package/src/lib/tasks/test-runner.js +410 -33
- package/src/lib/validators/checkpoint-persistence.js +39 -39
- package/src/lib/validators/css/css-validator.js +340 -340
- package/src/lib/validators/shared/emit-validator-dispatch.js +14 -14
- package/src/lib/validators/shared/issue-counter.js +14 -14
- package/src/lib/validators/verify-runner.js +583 -28
- package/src/lib/worktree/docker-audit.js +287 -0
- package/src/lib/worktree/env-allocator.js +24 -0
- package/src/lib/worktree/worktree-audit.js +30 -1
- package/src/scripts/setup-infra.js +24 -11
- package/src/utils/agent-id-mapper.js +11 -11
- package/src/utils/agents-installer.js +18 -8
- package/src/utils/claude-md-injector.js +10 -5
- package/src/utils/claude-settings-manager.js +300 -300
- package/src/utils/file-copier.js +11 -4
- package/src/utils/hooks-installer.js +29 -26
- package/src/utils/skills-installer.js +36 -29
- package/src/utils/version-checker.js +68 -3
- package/framework/standards/ai-agents/prompts-in-db.md +0 -214
|
@@ -1006,8 +1006,15 @@ function isLiveSiblingWorktreeRegistration(relPath, root, feature) {
|
|
|
1006
1006
|
* @param {string} rootPath - the primary root, for the replica comparison
|
|
1007
1007
|
* @param {{ discardIgnored?: boolean }} options
|
|
1008
1008
|
* @returns {{ shieldable: string[], blocking: string[], discarded: string[], replicable: string[] }}
|
|
1009
|
+
*
|
|
1010
|
+
* EXPORTADA para que o `finish --dry-run` (pré-voo) responda EXATAMENTE a
|
|
1011
|
+
* mesma pergunta que o teardown real vai responder. Uma segunda enumeração de
|
|
1012
|
+
* `git status --ignored` no finish.js — com a sua própria cópia de
|
|
1013
|
+
* IGNORED_SHIELDABLE_PREFIXES — faria o pré-voo prometer uma coisa e o
|
|
1014
|
+
* comando fazer outra, que é a única maneira de um dry-run ser pior que
|
|
1015
|
+
* nenhum. Consumida read-only: o pré-voo não copia, não apaga, não decide.
|
|
1009
1016
|
*/
|
|
1010
|
-
function classifyIgnoredLeftovers(worktreePath, rootPath, options = {}) {
|
|
1017
|
+
export function classifyIgnoredLeftovers(worktreePath, rootPath, options = {}) {
|
|
1011
1018
|
let out;
|
|
1012
1019
|
try {
|
|
1013
1020
|
// `-z` + execFile: NUL-delimited, no shell, no C-style quoting to undo —
|
|
@@ -198,7 +198,23 @@ export async function advanceCommand(featureName, options = {}) {
|
|
|
198
198
|
process.exit(1);
|
|
199
199
|
}
|
|
200
200
|
|
|
201
|
-
|
|
201
|
+
// Gate idempotency (F15): `setApprovalGate` REPLACES the gate object whole
|
|
202
|
+
// (state-manager.js), so re-writing an already-approved gate does not
|
|
203
|
+
// refresh it — it destroys `approvedBy`, `timestamp`, `notes` and
|
|
204
|
+
// `selfAssessed` in one assignment. And `resolveApprovedBy` above answers
|
|
205
|
+
// "auto" in every headless context, so `approve f proposal --approver
|
|
206
|
+
// lucas` followed by `advance f` used to rewrite a human's signature as
|
|
207
|
+
// "auto" — the one stamp the charter forbids on a human-approved gate.
|
|
208
|
+
// The state-sync hook already carries exactly this guard; `advance`, the
|
|
209
|
+
// other gate write-path, simply never got it.
|
|
210
|
+
//
|
|
211
|
+
// It skips ONLY the write. The scaffold and the handoff below still run,
|
|
212
|
+
// so re-running `advance` after a failed scaffold keeps working — the
|
|
213
|
+
// reason this is a guard and not an abort.
|
|
214
|
+
const priorGate = gate ? feature.approvalGates?.[gate] : null;
|
|
215
|
+
const alreadyApproved = priorGate?.approved === true;
|
|
216
|
+
|
|
217
|
+
if (gate && !alreadyApproved) {
|
|
202
218
|
await setApprovalGate(featureName, gate, true, {
|
|
203
219
|
approvedBy,
|
|
204
220
|
approvedAt: new Date().toISOString(),
|
|
@@ -226,7 +242,13 @@ export async function advanceCommand(featureName, options = {}) {
|
|
|
226
242
|
if (missingArtifacts.length) {
|
|
227
243
|
console.log(chalk.yellow(` ⚠️ --force: avançou SEM ${missingArtifacts.join(', ')}.`));
|
|
228
244
|
}
|
|
229
|
-
|
|
245
|
+
// Report what actually happened: claiming "approved (auto)" when nothing
|
|
246
|
+
// was written is how the destroyed signature stayed invisible.
|
|
247
|
+
if (gate && alreadyApproved) {
|
|
248
|
+
console.log(chalk.gray(` Gate "${gate}" was already approved (${priorGate.approvedBy || 'unknown'}) — approval preserved, nothing re-written.`));
|
|
249
|
+
} else if (gate) {
|
|
250
|
+
console.log(chalk.gray(` Gate "${gate}" approved (${approvedBy}).`));
|
|
251
|
+
}
|
|
230
252
|
if (nextDir) console.log(chalk.gray(` Scaffolded ${nextDir}/ — ready for the next phase's first artifact.\n`));
|
|
231
253
|
else console.log('');
|
|
232
254
|
} catch (error) {
|
|
@@ -180,7 +180,13 @@ export async function approveCommand(featureName, gateName, options = {}) {
|
|
|
180
180
|
if (currentStatus?.approved) {
|
|
181
181
|
console.log(chalk.yellow(`\n⚠️ Gate "${gateName}" is already approved`));
|
|
182
182
|
console.log(chalk.gray(`Approved at: ${currentStatus.timestamp}`));
|
|
183
|
-
console.log(chalk.gray(`Approved by: ${currentStatus.approvedBy || 'Unknown'}
|
|
183
|
+
console.log(chalk.gray(`Approved by: ${currentStatus.approvedBy || 'Unknown'}`));
|
|
184
|
+
// This early-out is a no-op that still exits 0 — deliberate, and
|
|
185
|
+
// `--force` does NOT cover it (that flag only covers gate ORDER). A
|
|
186
|
+
// caller who meant to re-approve therefore reads success and is left
|
|
187
|
+
// with nowhere to go. The way out already exists as `unapprove`; the
|
|
188
|
+
// message just never named it. Naming it is the whole fix (no new flag).
|
|
189
|
+
console.log(chalk.gray(`To approve it again, revoke it first: morph-spec unapprove ${featureName} ${gateName}\n`));
|
|
184
190
|
return;
|
|
185
191
|
}
|
|
186
192
|
|
|
@@ -349,6 +355,32 @@ export async function approveCommand(featureName, gateName, options = {}) {
|
|
|
349
355
|
}
|
|
350
356
|
selfAssessed = true;
|
|
351
357
|
}
|
|
358
|
+
|
|
359
|
+
// REAVALIAÇÃO VISÍVEL. O `evaluator-report.md` é append-only, então uma
|
|
360
|
+
// segunda rodada acrescenta um `**Composite-Score:**` ao fim e o arquivo
|
|
361
|
+
// passa a carregar mais de um veredito. O gate decide pelo ÚLTIMO (o
|
|
362
|
+
// vigente) — mas aprovar em silêncio um relatório com notas superadas
|
|
363
|
+
// esconde do humano exatamente o fato que ele precisa ver: a nota MUDOU,
|
|
364
|
+
// e numa das rodadas medidas em campo ela CAIU (8.9 → 8.3, quando uma
|
|
365
|
+
// correção abriu um bloqueante).
|
|
366
|
+
//
|
|
367
|
+
// Aqui é o lugar: `approve` é a precondição humana do Gate 3 e a única
|
|
368
|
+
// superfície onde uma pessoa lê o veredito antes de carimbá-lo. Sem este
|
|
369
|
+
// bloco, `scoreTokens`/`superseded` seriam mitigação inerte — campo que
|
|
370
|
+
// ninguém lê não mitiga nada.
|
|
371
|
+
if (report.status === 'ok' && report.scoreTokens > 1) {
|
|
372
|
+
console.log(chalk.yellow(
|
|
373
|
+
`
|
|
374
|
+
⚠️ O relatório do avaliador tem ${report.scoreTokens} vereditos (o arquivo é append-only).`
|
|
375
|
+
));
|
|
376
|
+
console.log(chalk.gray(` Vigente (o que o gate usa): ${report.score}`));
|
|
377
|
+
console.log(chalk.gray(` Superado(s), na ordem do arquivo: ${report.superseded.join(', ')}`));
|
|
378
|
+
if (report.superseded.some((n) => n > report.score)) {
|
|
379
|
+
console.log(chalk.yellow(' A nota CAIU em relação a uma rodada anterior — confira o que a correção'));
|
|
380
|
+
console.log(chalk.yellow(' abriu antes de aprovar; o relatório mantém a análise das duas rodadas.'));
|
|
381
|
+
}
|
|
382
|
+
console.log('');
|
|
383
|
+
}
|
|
352
384
|
}
|
|
353
385
|
}
|
|
354
386
|
|
|
@@ -15,32 +15,61 @@ import { detectDefaultBranch } from '../../lib/git/default-branch.js';
|
|
|
15
15
|
* `morph-spec finish` can later merge/PR it back. Symmetric with the worktree
|
|
16
16
|
* flow, which gets its branch from `runWorktreeSetup`.
|
|
17
17
|
*
|
|
18
|
+
* That checkout moves the dev's PRIMARY working tree, and `stdio: 'pipe'`
|
|
19
|
+
* swallows even git's own message — so the move is reported by the caller
|
|
20
|
+
* (`branchMoveWarning`), never silent. `checkout: false` (`--no-checkout`)
|
|
21
|
+
* still CREATES the branch — `finish --pr|--merge` depends on it existing in
|
|
22
|
+
* both flows — and only skips moving the tree.
|
|
23
|
+
*
|
|
18
24
|
* Fail-open: outside a git repo, with no resolvable default, or on any git
|
|
19
25
|
* error, the feature is simply left on the current branch — never a failed birth.
|
|
20
26
|
*
|
|
21
27
|
* @param {string} featureName
|
|
22
|
-
* @
|
|
28
|
+
* @param {{ checkout?: boolean }} [opts] - `checkout: false` keeps the tree put
|
|
29
|
+
* @returns {{ branched: boolean, checkedOut: boolean, branch?: string, from?: string,
|
|
30
|
+
* movedFrom?: string, stayedOn?: string, reason?: string }}
|
|
31
|
+
* `movedFrom` is present ONLY when the working tree actually moved (it names
|
|
32
|
+
* the branch left behind); `stayedOn` only when the move was declined.
|
|
23
33
|
*/
|
|
24
|
-
function branchCommonFlow(featureName) {
|
|
34
|
+
function branchCommonFlow(featureName, { checkout = true } = {}) {
|
|
25
35
|
const cwd = process.cwd();
|
|
26
36
|
try {
|
|
27
|
-
if (!isGitRepo(cwd)) return { branched: false, reason: 'not-a-git-repo' };
|
|
37
|
+
if (!isGitRepo(cwd)) return { branched: false, checkedOut: false, reason: 'not-a-git-repo' };
|
|
28
38
|
const branch = buildBranchName(featureName);
|
|
29
39
|
const defaultBranch = detectDefaultBranch(cwd);
|
|
30
|
-
if (!defaultBranch) return { branched: false, reason: 'no-default-branch' };
|
|
40
|
+
if (!defaultBranch) return { branched: false, checkedOut: false, reason: 'no-default-branch' };
|
|
31
41
|
if (!branchExists(branch, cwd)) {
|
|
32
42
|
execFileSync('git', ['branch', branch, defaultBranch], { cwd, stdio: 'pipe' });
|
|
33
43
|
}
|
|
34
44
|
const current = execFileSync('git', ['rev-parse', '--abbrev-ref', 'HEAD'], { cwd, stdio: 'pipe' }).toString().trim();
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
}
|
|
38
|
-
|
|
45
|
+
// Already there: nothing moved, so nothing to warn about.
|
|
46
|
+
if (current === branch) return { branched: true, checkedOut: true, branch, from: defaultBranch };
|
|
47
|
+
if (!checkout) return { branched: true, checkedOut: false, branch, from: defaultBranch, stayedOn: current };
|
|
48
|
+
execFileSync('git', ['checkout', branch], { cwd, stdio: 'pipe' });
|
|
49
|
+
return { branched: true, checkedOut: true, branch, from: defaultBranch, movedFrom: current };
|
|
39
50
|
} catch {
|
|
40
|
-
return { branched: false, reason: 'git-error' };
|
|
51
|
+
return { branched: false, checkedOut: false, reason: 'git-error' };
|
|
41
52
|
}
|
|
42
53
|
}
|
|
43
54
|
|
|
55
|
+
/**
|
|
56
|
+
* The alert for a checkout that MOVED. Built once and rendered on both
|
|
57
|
+
* surfaces — stdout (human) and stderr (under `--json`, so it survives a
|
|
58
|
+
* stdout redirect) — so the two can never drift apart.
|
|
59
|
+
*
|
|
60
|
+
* @param {{ branch: string, movedFrom: string }} branchResult
|
|
61
|
+
* @returns {string[]} lines, unstyled and unindented
|
|
62
|
+
*/
|
|
63
|
+
function branchMoveWarning({ branch, movedFrom }) {
|
|
64
|
+
return [
|
|
65
|
+
`⚠️ Working tree MOVED: ${movedFrom} → ${branch}`,
|
|
66
|
+
` This checkout is now ON the feature branch — uncommitted work came along,`,
|
|
67
|
+
` and anything committed here from now on lands on ${branch}, not ${movedFrom}.`,
|
|
68
|
+
` Use --no-checkout to create the branch without moving the tree, or --worktree`,
|
|
69
|
+
` (the recommended route for parallel work) to isolate the feature in its own tree.`,
|
|
70
|
+
];
|
|
71
|
+
}
|
|
72
|
+
|
|
44
73
|
/** Feature names are kebab-case: lowercase alphanumerics and hyphens. */
|
|
45
74
|
const FEATURE_NAME_RE = /^[a-z0-9][a-z0-9-]*$/;
|
|
46
75
|
|
|
@@ -130,6 +159,24 @@ export async function createCommand(featureName, options = {}) {
|
|
|
130
159
|
process.exit(1);
|
|
131
160
|
}
|
|
132
161
|
|
|
162
|
+
// `--no-checkout` pede que o checkout PRINCIPAL não se mova; `--worktree`
|
|
163
|
+
// nunca o move — a feature nasce numa árvore separada, e o caminho de
|
|
164
|
+
// worktree sequer chama `branchCommonFlow`, que é o único leitor do flag.
|
|
165
|
+
// Aceitar a combinação em silêncio é dizer que o CLI honrou um pedido que
|
|
166
|
+
// ele ignorou — o mesmo anti-padrão que esta série de fixes tirou do
|
|
167
|
+
// `finish --pr --push`. Recusa ALTA, e AQUI: junto das outras validações
|
|
168
|
+
// de forma, ANTES de `createFeature` — a primeira mutação do `create`.
|
|
169
|
+
// Uma recusa depois dela deixaria a feature nascida por um comando que
|
|
170
|
+
// falhou, pior que o no-op que ela substitui.
|
|
171
|
+
if (options.worktree && options.checkout === false) {
|
|
172
|
+
console.error(chalk.red(`\n❌ no-checkout-with-worktree: --no-checkout não se combina com --worktree`));
|
|
173
|
+
console.error(chalk.gray(` O --worktree já não move o checkout desta árvore: a feature nasce em worktrees/${featureName},`));
|
|
174
|
+
console.error(chalk.gray(` na branch morph/${featureName}, e o caminho de worktree nem chega a ler o --no-checkout.`));
|
|
175
|
+
console.error(chalk.gray(` Para isolar a feature na própria árvore: morph-spec create ${featureName} --worktree`));
|
|
176
|
+
console.error(chalk.gray(` Para criar só a branch morph/${featureName} sem mover esta árvore: morph-spec create ${featureName} --no-checkout\n`));
|
|
177
|
+
process.exit(1);
|
|
178
|
+
}
|
|
179
|
+
|
|
133
180
|
const now = new Date().toISOString();
|
|
134
181
|
const { workType, workTypeDetection } = resolveWorkType(options, now);
|
|
135
182
|
|
|
@@ -225,7 +272,8 @@ export async function createCommand(featureName, options = {}) {
|
|
|
225
272
|
} else {
|
|
226
273
|
// Common flow: still isolate the feature on its own branch so `finish`
|
|
227
274
|
// can merge/PR it back. Fail-open (see branchCommonFlow).
|
|
228
|
-
|
|
275
|
+
// Commander's `--no-checkout` sets options.checkout === false.
|
|
276
|
+
branchResult = branchCommonFlow(featureName, { checkout: options.checkout !== false });
|
|
229
277
|
}
|
|
230
278
|
}
|
|
231
279
|
|
|
@@ -238,6 +286,11 @@ export async function createCommand(featureName, options = {}) {
|
|
|
238
286
|
const out = { feature: featureName, created, ...finalFeature };
|
|
239
287
|
if (worktreeResult) out.worktree = worktreeResult;
|
|
240
288
|
if (branchResult) out.branch = branchResult;
|
|
289
|
+
// The move of the PRIMARY checkout is never silent — under --json it goes
|
|
290
|
+
// to stderr so it survives `... --json > out.json` instead of vanishing.
|
|
291
|
+
if (branchResult?.movedFrom) {
|
|
292
|
+
console.error(chalk.yellow(branchMoveWarning(branchResult).join('\n')));
|
|
293
|
+
}
|
|
241
294
|
console.log(JSON.stringify(out, null, 2));
|
|
242
295
|
return;
|
|
243
296
|
}
|
|
@@ -262,7 +315,15 @@ export async function createCommand(featureName, options = {}) {
|
|
|
262
315
|
}
|
|
263
316
|
} else if (branchResult?.branched) {
|
|
264
317
|
console.log(chalk.green(` branch: ${branchResult.branch} (from ${branchResult.from})`));
|
|
265
|
-
console.log(chalk.gray(` close it with: morph-spec finish ${featureName} --pr | --merge
|
|
318
|
+
console.log(chalk.gray(` close it with: morph-spec finish ${featureName} --pr | --merge`));
|
|
319
|
+
if (branchResult.movedFrom) {
|
|
320
|
+
// Alert, not one more success line: the tree the dev is standing in moved.
|
|
321
|
+
console.log('');
|
|
322
|
+
for (const line of branchMoveWarning(branchResult)) console.log(chalk.yellow(` ${line}`));
|
|
323
|
+
} else if (branchResult.checkedOut === false) {
|
|
324
|
+
console.log(chalk.gray(` working tree left on ${branchResult.stayedOn} (--no-checkout)`));
|
|
325
|
+
}
|
|
326
|
+
console.log('');
|
|
266
327
|
}
|
|
267
328
|
} else {
|
|
268
329
|
console.log(chalk.yellow(`\n⚠️ Feature "${featureName}" already exists — left untouched`));
|