@polymorphism-tech/morph-spec 3.1.0 → 4.2.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 +882 -3
- package/README.md +79 -18
- package/bin/detect-agents.js +1 -1
- package/bin/morph-spec.js +163 -26
- package/bin/task-manager.cjs +101 -7
- package/bin/validate.js +1 -1
- package/docs/cli-auto-detection.md +219 -0
- package/docs/getting-started.md +0 -5
- package/docs/llm-interaction-config.md +735 -0
- package/docs/troubleshooting.md +269 -0
- package/docs/v3.0/AGENTS.md +521 -0
- package/docs/v3.0/ANALYSIS.md +555 -0
- package/docs/v3.0/ARCHITECTURE.md +436 -0
- package/docs/v3.0/EXECUTION-FLOW.md +1304 -0
- package/docs/v3.0/FEATURES.md +688 -0
- package/docs/v3.0/README.md +231 -0
- package/docs/v3.0/ROADMAP.md +801 -0
- package/docs/validation-checklist.md +0 -1
- package/package.json +5 -1
- package/src/commands/agents/index.js +4 -0
- package/src/commands/agents/spawn-team.js +172 -0
- package/src/commands/{create-story.js → feature/create-story.js} +357 -354
- package/src/commands/feature/index.js +6 -0
- package/src/commands/{shard-spec.js → feature/shard-spec.js} +2 -2
- package/src/commands/{sprint-status.js → feature/sprint-status.js} +1 -1
- package/src/commands/{generate-context.js → generation/generate-context.js} +40 -40
- package/src/commands/{generate.js → generation/generate.js} +130 -3
- package/src/commands/generation/index.js +5 -0
- package/src/commands/index.js +16 -0
- package/src/commands/learning/capture-pattern.js +121 -0
- package/src/commands/learning/index.js +5 -0
- package/src/commands/learning/search-patterns.js +126 -0
- package/src/commands/{detect-agents.js → project/detect-agents.js} +178 -178
- package/src/commands/project/detect-workflow.js +174 -0
- package/src/commands/{detect.js → project/detect.js} +104 -104
- package/src/commands/{doctor.js → project/doctor.js} +356 -356
- package/src/commands/project/index.js +10 -0
- package/src/commands/{init.js → project/init.js} +305 -258
- package/src/commands/{sync.js → project/sync.js} +167 -167
- package/src/commands/{update.js → project/update.js} +240 -204
- package/src/commands/{advance-phase.js → state/advance-phase.js} +416 -266
- package/src/commands/state/approve.js +221 -0
- package/src/commands/state/index.js +8 -0
- package/src/commands/{rollback-phase.js → state/rollback-phase.js} +185 -185
- package/src/commands/{state.js → state/state.js} +334 -334
- package/src/commands/{validate-phase.js → state/validate-phase.js} +221 -221
- package/src/commands/tasks/index.js +4 -0
- package/src/commands/{task.js → tasks/task.js} +78 -78
- package/src/commands/templates/index.js +8 -0
- package/src/commands/templates/template-customize.js +101 -0
- package/src/commands/templates/template-list.js +128 -0
- package/src/commands/templates/template-render.js +95 -0
- package/src/commands/templates/template-show.js +131 -0
- package/src/commands/templates/template-validate.js +91 -0
- package/src/commands/utils/index.js +7 -0
- package/src/commands/utils/migrate-state.js +158 -0
- package/src/commands/{session-summary.js → utils/session-summary.js} +291 -291
- package/src/commands/{troubleshoot.js → utils/troubleshoot.js} +222 -222
- package/src/commands/utils/upgrade.js +346 -0
- package/src/commands/{analyze-blazor-concurrency.js → validation/analyze-blazor-concurrency.js} +193 -193
- package/src/commands/validation/index.js +8 -0
- package/src/commands/{lint-fluent.js → validation/lint-fluent.js} +352 -352
- package/src/commands/{validate-blazor-state.js → validation/validate-blazor-state.js} +210 -210
- package/src/commands/{validate-blazor.js → validation/validate-blazor.js} +156 -156
- package/src/commands/{validate-css.js → validation/validate-css.js} +84 -84
- package/src/core/index.js +10 -0
- package/src/core/registry/command-registry.js +302 -0
- package/src/core/registry/index.js +8 -0
- package/src/core/registry/validator-registry.js +204 -0
- package/src/core/state/index.js +8 -0
- package/src/core/state/phase-state-machine.js +214 -0
- package/src/{lib → core/state}/state-manager.js +572 -414
- package/src/core/templates/index.js +9 -0
- package/src/core/templates/template-data-sources.js +325 -0
- package/src/core/templates/template-registry.js +335 -0
- package/src/core/templates/template-renderer.js +477 -0
- package/src/core/templates/template-validator.js +296 -0
- package/src/core/workflows/index.js +7 -0
- package/src/core/workflows/workflow-detector.js +354 -0
- package/src/generator/config-generator.js +206 -0
- package/src/generator/templates/config.json.template +40 -0
- package/src/generator/templates/project.md.template +67 -0
- package/src/lib/{complexity-analyzer.js → analysis/complexity-analyzer.js} +441 -441
- package/src/lib/analysis/index.js +7 -0
- package/src/lib/checkpoints/checkpoint-hooks.js +258 -0
- package/src/lib/checkpoints/index.js +7 -0
- package/src/lib/detectors/config-detector.js +223 -223
- package/src/lib/detectors/conversation-analyzer.js +163 -163
- package/src/lib/{design-system-detector.js → detectors/design-system-detector.js} +187 -187
- package/src/lib/detectors/index.js +87 -84
- package/src/lib/detectors/standards-generator.js +275 -275
- package/src/lib/detectors/structure-detector.js +245 -245
- package/src/lib/{context-generator.js → generators/context-generator.js} +526 -516
- package/src/lib/generators/index.js +10 -0
- package/src/lib/generators/metadata-extractor.js +387 -0
- package/src/lib/{recap-generator.js → generators/recap-generator.js} +205 -205
- package/src/lib/learning/index.js +7 -0
- package/src/lib/orchestration/index.js +7 -0
- package/src/lib/{team-orchestrator.js → orchestration/team-orchestrator.js} +323 -323
- package/src/lib/stacks/index.js +7 -0
- package/src/lib/{stack-resolver.js → stacks/stack-resolver.js} +180 -148
- package/src/lib/standards/index.js +7 -0
- package/src/lib/{standards-context-injector.js → standards/standards-context-injector.js} +298 -288
- package/src/lib/troubleshooting/index.js +8 -0
- package/src/lib/{troubleshoot-grep.js → troubleshooting/troubleshoot-grep.js} +204 -204
- package/src/lib/{troubleshoot-index.js → troubleshooting/troubleshoot-index.js} +144 -144
- package/src/lib/validators/architecture/architecture-validator.js +387 -0
- package/src/lib/validators/architecture/index.js +7 -0
- package/src/lib/validators/architecture-validator.js +40 -367
- package/src/lib/{blazor-concurrency-analyzer.js → validators/blazor/blazor-concurrency-analyzer.js} +277 -288
- package/src/lib/{blazor-state-validator.js → validators/blazor/blazor-state-validator.js} +279 -291
- package/src/lib/{blazor-validator.js → validators/blazor/blazor-validator.js} +369 -374
- package/src/lib/validators/blazor/index.js +9 -0
- package/src/lib/validators/content/content-validator.js +351 -0
- package/src/lib/validators/content/index.js +7 -0
- package/src/lib/validators/content-validator.js +164 -0
- package/src/lib/validators/{contract-compliance-validator.js → contracts/contract-compliance-validator.js} +273 -273
- package/src/lib/validators/contracts/index.js +7 -0
- package/src/lib/{css-validator.js → validators/css/css-validator.js} +352 -352
- package/src/lib/validators/css/index.js +7 -0
- package/src/lib/validators/{design-system-validator.js → design-system/design-system-validator.js} +231 -231
- package/src/lib/validators/design-system/index.js +7 -0
- package/src/lib/validators/package-validator.js +41 -340
- package/src/lib/validators/packages/index.js +7 -0
- package/src/lib/validators/packages/package-validator.js +360 -0
- package/src/lib/validators/shared/index.js +12 -0
- package/src/lib/validators/shared/issue-counter.js +18 -0
- package/src/lib/validators/shared/result-formatter.js +124 -0
- package/src/lib/{spec-validator.js → validators/spec-validator.js} +258 -258
- package/src/lib/validators/ui/index.js +7 -0
- package/src/lib/validators/ui/ui-contrast-validator.js +422 -0
- package/src/lib/validators/ui-contrast-validator.js +31 -409
- package/src/lib/{validation-runner.js → validators/validation-runner.js} +286 -284
- package/src/llm/analyzer.js +215 -0
- package/src/llm/environment-detector.js +43 -0
- package/src/llm/few-shot-examples.js +216 -0
- package/src/llm/project-config-schema.json +188 -0
- package/src/llm/prompt-builder.js +96 -0
- package/src/orchestrator.js +206 -0
- package/src/sanitizer/context-sanitizer.js +221 -0
- package/src/sanitizer/patterns.js +163 -0
- package/src/scanner/project-scanner.js +242 -0
- package/src/ui/diff-display.js +91 -0
- package/src/ui/interactive-wizard.js +96 -0
- package/src/ui/user-review.js +211 -0
- package/src/ui/wizard-questions.js +188 -0
- package/src/utils/color-utils.js +70 -0
- package/src/utils/file-copier.js +188 -189
- package/src/utils/process-handler.js +97 -0
- package/src/writer/file-writer.js +86 -0
- package/stacks/blazor-azure/.claude/skills/level-2-domains/ai-agents/ai-system-architect.md +3 -3
- package/stacks/blazor-azure/.claude/skills/level-2-domains/backend/api-designer.md +59 -0
- package/stacks/blazor-azure/.claude/skills/level-2-domains/backend/dotnet-senior.md +45 -255
- package/stacks/blazor-azure/.claude/skills/level-2-domains/backend/ef-modeler.md +33 -88
- package/stacks/blazor-azure/.claude/skills/level-2-domains/backend/ms-agent-expert.md +25 -89
- package/stacks/blazor-azure/.claude/skills/level-2-domains/integrations/hangfire-orchestrator.md +64 -0
- package/stacks/blazor-azure/.morph/config/agents.json +879 -764
- package/stacks/blazor-azure/.morph/hooks/{pre-commit-tests.sh → pre-commit/tests-csharp.sh} +3 -2
- package/stacks/blazor-azure/.morph/templates/.gitkeep +0 -0
- package/stacks/blazor-azure/.morph/templates/infrastructure/github/workflows/cd-prod.yml.hbs +41 -0
- package/stacks/blazor-azure/.morph/templates/infrastructure/github/workflows/cd-staging.yml.hbs +24 -0
- package/stacks/blazor-azure/.morph/templates/infrastructure/github/workflows/ci-build.yml.hbs +23 -0
- package/stacks/nextjs-supabase/.claude/commands/morph-apply.md +221 -0
- package/stacks/nextjs-supabase/.claude/commands/morph-archive.md +79 -0
- package/stacks/nextjs-supabase/.claude/commands/morph-deploy.md +529 -0
- package/stacks/nextjs-supabase/.claude/commands/morph-infra.md +209 -0
- package/stacks/nextjs-supabase/.claude/commands/morph-preflight.md +227 -0
- package/stacks/nextjs-supabase/.claude/commands/morph-proposal.md +122 -0
- package/stacks/nextjs-supabase/.claude/commands/morph-status.md +86 -0
- package/stacks/nextjs-supabase/.claude/commands/morph-troubleshoot.md +122 -0
- package/stacks/nextjs-supabase/.claude/settings.local.json +6 -0
- package/stacks/nextjs-supabase/.claude/skills/level-2-domains/integrations/supabase-expert.md +30 -150
- package/stacks/nextjs-supabase/.morph/config/agents.json +345 -345
- package/stacks/nextjs-supabase/.morph/hooks/pre-commit/tests-typescript.sh +61 -0
- package/stacks/nextjs-supabase/.morph/templates/.gitkeep +0 -0
- package/stacks/nextjs-supabase/.morph/templates/infrastructure/github/workflows/cd-prod.yml.hbs +22 -0
- package/stacks/nextjs-supabase/.morph/templates/infrastructure/github/workflows/cd-staging.yml.hbs +22 -0
- package/stacks/nextjs-supabase/.morph/templates/infrastructure/github/workflows/ci-build.yml.hbs +35 -0
- package/stacks/nextjs-supabase/README.md +6 -15
- package/bin/render-template.js +0 -303
- package/bin/semantic-detect-agents.js +0 -247
- package/bin/validate-agents-skills.js +0 -257
- package/bin/validate-agents.js +0 -70
- package/bin/validate-phase.js +0 -263
- package/docs/examples.md +0 -328
- package/scripts/reorganize-skills.cjs +0 -175
- package/scripts/validate-agents-structure.cjs +0 -52
- package/scripts/validate-skills.cjs +0 -180
- package/src/commands/deploy.js +0 -780
- package/src/lib/continuous-validator.js +0 -421
- package/src/lib/decision-constraint-loader.js +0 -109
- package/src/lib/design-system-scaffolder.js +0 -299
- package/src/lib/hook-executor.js +0 -257
- package/src/lib/mockup-generator.js +0 -366
- package/src/lib/ui-detector.js +0 -350
- package/stacks/blazor-azure/.azure/README.md +0 -293
- package/stacks/blazor-azure/.azure/docs/azure-devops-setup.md +0 -454
- package/stacks/blazor-azure/.azure/docs/branch-strategy.md +0 -398
- package/stacks/blazor-azure/.azure/docs/local-development.md +0 -515
- package/stacks/blazor-azure/.azure/pipelines/pipeline-variables.yml +0 -34
- package/stacks/blazor-azure/.azure/pipelines/prod-pipeline.yml +0 -319
- package/stacks/blazor-azure/.azure/pipelines/staging-pipeline.yml +0 -234
- package/stacks/blazor-azure/.azure/pipelines/templates/build-dotnet.yml +0 -75
- package/stacks/blazor-azure/.azure/pipelines/templates/deploy-app-service.yml +0 -94
- package/stacks/blazor-azure/.azure/pipelines/templates/deploy-container-app.yml +0 -120
- package/stacks/blazor-azure/.azure/pipelines/templates/infra-deploy.yml +0 -90
- package/stacks/blazor-azure/.claude/settings.local.json +0 -15
- package/stacks/blazor-azure/.morph/docs/STORY-DRIVEN-DEVELOPMENT.md +0 -392
- package/stacks/blazor-azure/.morph/docs/workflows/design-impl.md +0 -37
- package/stacks/blazor-azure/.morph/docs/workflows/enforcement-pipeline.md +0 -668
- package/stacks/blazor-azure/.morph/docs/workflows/fast-track.md +0 -29
- package/stacks/blazor-azure/.morph/docs/workflows/full-morph.md +0 -76
- package/stacks/blazor-azure/.morph/docs/workflows/standard.md +0 -44
- package/stacks/blazor-azure/.morph/docs/workflows/ui-refresh.md +0 -39
- package/stacks/blazor-azure/.morph/examples/api-nextjs/README.md +0 -241
- package/stacks/blazor-azure/.morph/examples/api-nextjs/contracts.ts +0 -307
- package/stacks/blazor-azure/.morph/examples/api-nextjs/spec.md +0 -399
- package/stacks/blazor-azure/.morph/examples/api-nextjs/tasks.md +0 -168
- package/stacks/blazor-azure/.morph/examples/micro-saas/README.md +0 -125
- package/stacks/blazor-azure/.morph/examples/micro-saas/contracts.cs +0 -358
- package/stacks/blazor-azure/.morph/examples/micro-saas/decisions.md +0 -246
- package/stacks/blazor-azure/.morph/examples/micro-saas/spec.md +0 -236
- package/stacks/blazor-azure/.morph/examples/micro-saas/tasks.md +0 -150
- package/stacks/blazor-azure/.morph/examples/multi-agent/README.md +0 -309
- package/stacks/blazor-azure/.morph/examples/multi-agent/contracts.cs +0 -433
- package/stacks/blazor-azure/.morph/examples/multi-agent/spec.md +0 -479
- package/stacks/blazor-azure/.morph/examples/multi-agent/tasks.md +0 -185
- package/stacks/blazor-azure/.morph/examples/scheduled-reports/decisions.md +0 -158
- package/stacks/blazor-azure/.morph/examples/scheduled-reports/proposal.md +0 -95
- package/stacks/blazor-azure/.morph/examples/scheduled-reports/spec.md +0 -267
- package/stacks/blazor-azure/.morph/examples/state-v3.json +0 -188
- package/stacks/blazor-azure/.morph/hooks/README.md +0 -348
- package/stacks/blazor-azure/.morph/hooks/pre-commit-agents.sh +0 -24
- package/stacks/blazor-azure/.morph/hooks/pre-commit-all.sh +0 -48
- package/stacks/blazor-azure/.morph/hooks/pre-commit-specs.sh +0 -49
- package/stacks/blazor-azure/.morph/hooks/task-completed.js +0 -73
- package/stacks/blazor-azure/.morph/hooks/teammate-idle.js +0 -68
- package/stacks/blazor-azure/.morph/standards/agent-framework-blazor-ui.md +0 -359
- package/stacks/blazor-azure/.morph/standards/agent-framework-production.md +0 -410
- package/stacks/blazor-azure/.morph/standards/agent-framework-setup.md +0 -413
- package/stacks/blazor-azure/.morph/standards/agent-framework-workflows.md +0 -349
- package/stacks/blazor-azure/.morph/standards/agent-teams-workflow.md +0 -474
- package/stacks/blazor-azure/.morph/standards/architecture.md +0 -325
- package/stacks/blazor-azure/.morph/standards/azure.md +0 -605
- package/stacks/blazor-azure/.morph/standards/coding.md +0 -377
- package/stacks/blazor-azure/.morph/standards/dotnet10-migration.md +0 -520
- package/stacks/blazor-azure/.morph/standards/fluent-ui-setup.md +0 -590
- package/stacks/blazor-azure/.morph/standards/migration-guide.md +0 -514
- package/stacks/blazor-azure/.morph/standards/passkeys-auth.md +0 -423
- package/stacks/blazor-azure/.morph/standards/vector-search-rag.md +0 -536
- package/stacks/blazor-azure/.morph/templates/CONTEXT-FEATURE.md +0 -276
- package/stacks/blazor-azure/.morph/templates/CONTEXT.md +0 -170
- package/stacks/blazor-azure/.morph/templates/FluentDesignTheme.cs +0 -149
- package/stacks/blazor-azure/.morph/templates/MudTheme.cs +0 -281
- package/stacks/blazor-azure/.morph/templates/agent.cs +0 -163
- package/stacks/blazor-azure/.morph/templates/clarify-questions.md +0 -159
- package/stacks/blazor-azure/.morph/templates/component.razor +0 -239
- package/stacks/blazor-azure/.morph/templates/contracts/Commands.cs +0 -74
- package/stacks/blazor-azure/.morph/templates/contracts/Entities.cs +0 -25
- package/stacks/blazor-azure/.morph/templates/contracts/Queries.cs +0 -74
- package/stacks/blazor-azure/.morph/templates/contracts/README.md +0 -74
- package/stacks/blazor-azure/.morph/templates/contracts.cs +0 -217
- package/stacks/blazor-azure/.morph/templates/decisions.md +0 -123
- package/stacks/blazor-azure/.morph/templates/design-system.css +0 -226
- package/stacks/blazor-azure/.morph/templates/infra/.dockerignore.example +0 -89
- package/stacks/blazor-azure/.morph/templates/infra/Dockerfile.example +0 -82
- package/stacks/blazor-azure/.morph/templates/infra/README.md +0 -286
- package/stacks/blazor-azure/.morph/templates/infra/app-insights.bicep +0 -63
- package/stacks/blazor-azure/.morph/templates/infra/app-service.bicep +0 -164
- package/stacks/blazor-azure/.morph/templates/infra/azure-pipelines-deploy.yml +0 -480
- package/stacks/blazor-azure/.morph/templates/infra/container-app-env.bicep +0 -49
- package/stacks/blazor-azure/.morph/templates/infra/container-app.bicep +0 -156
- package/stacks/blazor-azure/.morph/templates/infra/deploy-checklist.md +0 -426
- package/stacks/blazor-azure/.morph/templates/infra/deploy.ps1 +0 -229
- package/stacks/blazor-azure/.morph/templates/infra/deploy.sh +0 -208
- package/stacks/blazor-azure/.morph/templates/infra/key-vault.bicep +0 -91
- package/stacks/blazor-azure/.morph/templates/infra/main.bicep +0 -189
- package/stacks/blazor-azure/.morph/templates/infra/parameters.dev.json +0 -29
- package/stacks/blazor-azure/.morph/templates/infra/parameters.prod.json +0 -29
- package/stacks/blazor-azure/.morph/templates/infra/parameters.staging.json +0 -29
- package/stacks/blazor-azure/.morph/templates/infra/sql-database.bicep +0 -103
- package/stacks/blazor-azure/.morph/templates/infra/storage.bicep +0 -106
- package/stacks/blazor-azure/.morph/templates/integrations/asaas-client.cs +0 -387
- package/stacks/blazor-azure/.morph/templates/integrations/asaas-webhook.cs +0 -351
- package/stacks/blazor-azure/.morph/templates/integrations/azure-identity-config.cs +0 -288
- package/stacks/blazor-azure/.morph/templates/integrations/clerk-config.cs +0 -258
- package/stacks/blazor-azure/.morph/templates/job.cs +0 -171
- package/stacks/blazor-azure/.morph/templates/migration.cs +0 -83
- package/stacks/blazor-azure/.morph/templates/proposal.md +0 -141
- package/stacks/blazor-azure/.morph/templates/recap.md +0 -94
- package/stacks/blazor-azure/.morph/templates/repository.cs +0 -141
- package/stacks/blazor-azure/.morph/templates/saas/subscription.cs +0 -347
- package/stacks/blazor-azure/.morph/templates/saas/tenant.cs +0 -338
- package/stacks/blazor-azure/.morph/templates/service.cs +0 -139
- package/stacks/blazor-azure/.morph/templates/simulation.md +0 -353
- package/stacks/blazor-azure/.morph/templates/spec.md +0 -149
- package/stacks/blazor-azure/.morph/templates/sprint-status.yaml +0 -68
- package/stacks/blazor-azure/.morph/templates/state.template.json +0 -222
- package/stacks/blazor-azure/.morph/templates/story.md +0 -143
- package/stacks/blazor-azure/.morph/templates/tasks.md +0 -257
- package/stacks/blazor-azure/.morph/templates/test.cs +0 -239
- package/stacks/blazor-azure/.morph/templates/ui-components.md +0 -362
- package/stacks/blazor-azure/.morph/templates/ui-design-system.md +0 -286
- package/stacks/blazor-azure/.morph/templates/ui-flows.md +0 -336
- package/stacks/blazor-azure/.morph/templates/ui-mockups.md +0 -133
- package/stacks/nextjs-supabase/.morph/docs/easypanel-setup.md +0 -169
- package/stacks/nextjs-supabase/.morph/docs/supabase-mcp-setup.md +0 -247
- package/stacks/nextjs-supabase/.morph/examples/crud-nextjs-supabase/README.md +0 -697
- package/stacks/nextjs-supabase/.morph/examples/crud-nextjs-supabase/spec.md +0 -85
- package/stacks/nextjs-supabase/.morph/examples/crud-nextjs-supabase/tasks.md +0 -86
- package/stacks/nextjs-supabase/.morph/examples/saas-nextjs-supabase/README.md +0 -498
- package/stacks/nextjs-supabase/.morph/examples/saas-nextjs-supabase/decisions.md +0 -121
- package/stacks/nextjs-supabase/.morph/examples/saas-nextjs-supabase/spec.md +0 -138
- package/stacks/nextjs-supabase/.morph/examples/saas-nextjs-supabase/tasks.md +0 -162
- package/stacks/nextjs-supabase/.morph/standards/easypanel-deploy.md +0 -191
- package/stacks/nextjs-supabase/.morph/standards/nextjs-patterns.md +0 -193
- package/stacks/nextjs-supabase/.morph/standards/supabase-auth.md +0 -171
- package/stacks/nextjs-supabase/.morph/standards/supabase-pgvector.md +0 -164
- package/stacks/nextjs-supabase/.morph/standards/supabase-rls.md +0 -179
- package/stacks/nextjs-supabase/.morph/standards/supabase-storage.md +0 -148
- package/stacks/nextjs-supabase/.morph/templates/contracts.cs +0 -173
- package/stacks/nextjs-supabase/.morph/templates/contracts.ts +0 -168
- package/stacks/nextjs-supabase/.morph/templates/decisions.md +0 -115
- package/stacks/nextjs-supabase/.morph/templates/dockerfile-api.dockerfile +0 -38
- package/stacks/nextjs-supabase/.morph/templates/dockerfile-web.dockerfile +0 -48
- package/stacks/nextjs-supabase/.morph/templates/proposal.md +0 -145
- package/stacks/nextjs-supabase/.morph/templates/recap.md +0 -134
- package/stacks/nextjs-supabase/.morph/templates/rls-policy.sql +0 -57
- package/stacks/nextjs-supabase/.morph/templates/spec.md +0 -231
- package/stacks/nextjs-supabase/.morph/templates/supabase-migration.sql +0 -100
- package/stacks/nextjs-supabase/.morph/templates/tasks.md +0 -257
- /package/src/lib/{design-system-generator.js → generators/design-system-generator.js} +0 -0
- /package/src/lib/{learning-system.js → learning/learning-system.js} +0 -0
package/src/lib/ui-detector.js
DELETED
|
@@ -1,350 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* UI Feature Detector
|
|
3
|
-
*
|
|
4
|
-
* Analyzes spec.md to detect UI needs automatically.
|
|
5
|
-
* Auto-triggers FASE 1.5: UI/UX when entities + CRUD are detected.
|
|
6
|
-
*
|
|
7
|
-
* MORPH-SPEC 3.0
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Detect UI needs from spec content
|
|
12
|
-
* @param {string} specContent - Content of spec.md
|
|
13
|
-
* @returns {Object} UI needs analysis
|
|
14
|
-
*/
|
|
15
|
-
export function detectUINeeds(specContent) {
|
|
16
|
-
const entities = parseEntities(specContent);
|
|
17
|
-
const crudOperations = detectCRUD(specContent);
|
|
18
|
-
const uiKeywords = detectUIKeywords(specContent);
|
|
19
|
-
|
|
20
|
-
const uiNeeds = [];
|
|
21
|
-
|
|
22
|
-
// Auto-detect CRUD UI needs
|
|
23
|
-
for (const entity of entities) {
|
|
24
|
-
if (crudOperations.create) {
|
|
25
|
-
uiNeeds.push({
|
|
26
|
-
type: 'form',
|
|
27
|
-
entity: entity.name,
|
|
28
|
-
operation: 'create',
|
|
29
|
-
fields: entity.properties,
|
|
30
|
-
priority: 'high'
|
|
31
|
-
});
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
if (crudOperations.read || crudOperations.list) {
|
|
35
|
-
uiNeeds.push({
|
|
36
|
-
type: 'list',
|
|
37
|
-
entity: entity.name,
|
|
38
|
-
fields: entity.properties.filter(p => p.displayInList !== false),
|
|
39
|
-
features: detectListFeatures(specContent),
|
|
40
|
-
priority: 'high'
|
|
41
|
-
});
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
if (crudOperations.update) {
|
|
45
|
-
uiNeeds.push({
|
|
46
|
-
type: 'form',
|
|
47
|
-
entity: entity.name,
|
|
48
|
-
operation: 'edit',
|
|
49
|
-
fields: entity.properties,
|
|
50
|
-
priority: 'medium'
|
|
51
|
-
});
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
if (crudOperations.delete) {
|
|
55
|
-
uiNeeds.push({
|
|
56
|
-
type: 'confirm-dialog',
|
|
57
|
-
entity: entity.name,
|
|
58
|
-
operation: 'delete',
|
|
59
|
-
priority: 'medium'
|
|
60
|
-
});
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
// Detect special UI components from keywords
|
|
65
|
-
if (uiKeywords.wizard) {
|
|
66
|
-
uiNeeds.push({
|
|
67
|
-
type: 'wizard',
|
|
68
|
-
steps: extractWizardSteps(specContent),
|
|
69
|
-
priority: 'high'
|
|
70
|
-
});
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
if (uiKeywords.dashboard) {
|
|
74
|
-
uiNeeds.push({
|
|
75
|
-
type: 'dashboard',
|
|
76
|
-
widgets: extractDashboardWidgets(specContent),
|
|
77
|
-
priority: 'high'
|
|
78
|
-
});
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
if (uiKeywords.upload) {
|
|
82
|
-
uiNeeds.push({
|
|
83
|
-
type: 'file-upload',
|
|
84
|
-
maxSize: extractMaxFileSize(specContent),
|
|
85
|
-
allowedTypes: extractAllowedFileTypes(specContent),
|
|
86
|
-
priority: 'high'
|
|
87
|
-
});
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
const shouldTriggerUIPhase = uiNeeds.length > 0 ||
|
|
91
|
-
entities.length > 0 ||
|
|
92
|
-
uiKeywords.hasUIKeywords;
|
|
93
|
-
|
|
94
|
-
return {
|
|
95
|
-
shouldTrigger: shouldTriggerUIPhase,
|
|
96
|
-
entities,
|
|
97
|
-
crudOperations,
|
|
98
|
-
uiNeeds,
|
|
99
|
-
keywords: uiKeywords,
|
|
100
|
-
confidence: calculateConfidence(entities, crudOperations, uiKeywords)
|
|
101
|
-
};
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
/**
|
|
105
|
-
* Parse entities from spec
|
|
106
|
-
*/
|
|
107
|
-
function parseEntities(specContent) {
|
|
108
|
-
const entities = [];
|
|
109
|
-
|
|
110
|
-
// Match pseudo-code entity definitions
|
|
111
|
-
const entityPattern = /(?:class|entity|table)\s+(\w+)\s*{([^}]+)}/gi;
|
|
112
|
-
let match;
|
|
113
|
-
|
|
114
|
-
while ((match = entityPattern.exec(specContent)) !== null) {
|
|
115
|
-
const entityName = match[1];
|
|
116
|
-
const body = match[2];
|
|
117
|
-
|
|
118
|
-
const properties = parseProperties(body);
|
|
119
|
-
|
|
120
|
-
entities.push({
|
|
121
|
-
name: entityName,
|
|
122
|
-
properties,
|
|
123
|
-
hasId: properties.some(p => p.name.toLowerCase() === 'id'),
|
|
124
|
-
hasTimestamps: properties.some(p =>
|
|
125
|
-
p.name.toLowerCase().includes('createdat') ||
|
|
126
|
-
p.name.toLowerCase().includes('updatedat')
|
|
127
|
-
)
|
|
128
|
-
});
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
return entities;
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
/**
|
|
135
|
-
* Parse properties from entity body
|
|
136
|
-
*/
|
|
137
|
-
function parseProperties(body) {
|
|
138
|
-
const properties = [];
|
|
139
|
-
const lines = body.split('\n').map(l => l.trim()).filter(l => l);
|
|
140
|
-
|
|
141
|
-
for (const line of lines) {
|
|
142
|
-
// Match: Type PropertyName or PropertyName: Type
|
|
143
|
-
const match = line.match(/(?:(\w+)\s+(\w+)|(\w+)\s*:\s*(\w+))/);
|
|
144
|
-
if (!match) continue;
|
|
145
|
-
|
|
146
|
-
const type = match[1] || match[4];
|
|
147
|
-
const name = match[2] || match[3];
|
|
148
|
-
|
|
149
|
-
if (!type || !name) continue;
|
|
150
|
-
|
|
151
|
-
properties.push({
|
|
152
|
-
name,
|
|
153
|
-
type,
|
|
154
|
-
isRequired: !line.includes('?') && !line.includes('optional'),
|
|
155
|
-
isNullable: line.includes('?'),
|
|
156
|
-
displayInList: !isInternalProperty(name),
|
|
157
|
-
isEnum: type.endsWith('Status') || type.endsWith('Type') || type.endsWith('Kind')
|
|
158
|
-
});
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
return properties;
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
/**
|
|
165
|
-
* Check if property is internal (not for display)
|
|
166
|
-
*/
|
|
167
|
-
function isInternalProperty(name) {
|
|
168
|
-
const internalNames = ['id', 'createdat', 'updatedat', 'deletedat', 'version', 'rowversion'];
|
|
169
|
-
return internalNames.includes(name.toLowerCase());
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
/**
|
|
173
|
-
* Detect CRUD operations from spec
|
|
174
|
-
*/
|
|
175
|
-
function detectCRUD(specContent) {
|
|
176
|
-
const lower = specContent.toLowerCase();
|
|
177
|
-
|
|
178
|
-
return {
|
|
179
|
-
create: /\b(create|add|new|insert|register|upload)\b/i.test(lower),
|
|
180
|
-
read: /\b(read|get|view|show|display|retrieve|fetch)\b/i.test(lower),
|
|
181
|
-
update: /\b(update|edit|modify|change)\b/i.test(lower),
|
|
182
|
-
delete: /\b(delete|remove|destroy)\b/i.test(lower),
|
|
183
|
-
list: /\b(list|index|all|search|filter|query)\b/i.test(lower)
|
|
184
|
-
};
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
/**
|
|
188
|
-
* Detect UI-specific keywords
|
|
189
|
-
*/
|
|
190
|
-
function detectUIKeywords(specContent) {
|
|
191
|
-
const lower = specContent.toLowerCase();
|
|
192
|
-
|
|
193
|
-
return {
|
|
194
|
-
wizard: /\b(wizard|step|multi-?step|flow)\b/i.test(lower),
|
|
195
|
-
dashboard: /\b(dashboard|overview|summary|stats|metrics)\b/i.test(lower),
|
|
196
|
-
chart: /\b(chart|graph|visualization|plot)\b/i.test(lower),
|
|
197
|
-
upload: /\b(upload|file|photo|image|document|attachment)\b/i.test(lower),
|
|
198
|
-
modal: /\b(modal|dialog|popup|overlay)\b/i.test(lower),
|
|
199
|
-
form: /\b(form|input|field|validation)\b/i.test(lower),
|
|
200
|
-
table: /\b(table|grid|list|datagrid)\b/i.test(lower),
|
|
201
|
-
hasUIKeywords: /\b(wizard|dashboard|chart|upload|modal|form|table|ui|ux|screen|page|component)\b/i.test(lower)
|
|
202
|
-
};
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
/**
|
|
206
|
-
* Detect list features (pagination, filters, etc.)
|
|
207
|
-
*/
|
|
208
|
-
function detectListFeatures(specContent) {
|
|
209
|
-
const lower = specContent.toLowerCase();
|
|
210
|
-
|
|
211
|
-
return {
|
|
212
|
-
pagination: /\b(paginat|page|per.?page|offset|limit)\b/i.test(lower),
|
|
213
|
-
sorting: /\b(sort|order|asc|desc)\b/i.test(lower),
|
|
214
|
-
filtering: /\b(filter|search|query|where)\b/i.test(lower),
|
|
215
|
-
selection: /\b(select|check|multi.?select|bulk)\b/i.test(lower),
|
|
216
|
-
actions: /\b(action|edit|delete|view|export)\b/i.test(lower)
|
|
217
|
-
};
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
/**
|
|
221
|
-
* Extract wizard steps from spec
|
|
222
|
-
*/
|
|
223
|
-
function extractWizardSteps(specContent) {
|
|
224
|
-
const steps = [];
|
|
225
|
-
const stepPattern = /step\s+(\d+):\s*([^\n]+)/gi;
|
|
226
|
-
let match;
|
|
227
|
-
|
|
228
|
-
while ((match = stepPattern.exec(specContent)) !== null) {
|
|
229
|
-
steps.push({
|
|
230
|
-
number: parseInt(match[1]),
|
|
231
|
-
title: match[2].trim()
|
|
232
|
-
});
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
return steps.length > 0 ? steps : [
|
|
236
|
-
{ number: 1, title: 'Information' },
|
|
237
|
-
{ number: 2, title: 'Confirmation' }
|
|
238
|
-
];
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
/**
|
|
242
|
-
* Extract dashboard widgets from spec
|
|
243
|
-
*/
|
|
244
|
-
function extractDashboardWidgets(specContent) {
|
|
245
|
-
const widgets = [];
|
|
246
|
-
|
|
247
|
-
if (/\b(stat|metric|kpi|count)\b/i.test(specContent)) {
|
|
248
|
-
widgets.push({ type: 'stat-card', count: 3 });
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
if (/\b(chart|graph|visualization)\b/i.test(specContent)) {
|
|
252
|
-
widgets.push({ type: 'chart', chartType: 'line' });
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
if (/\b(table|grid|list|recent)\b/i.test(specContent)) {
|
|
256
|
-
widgets.push({ type: 'data-table', showActions: true });
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
return widgets;
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
/**
|
|
263
|
-
* Extract max file size from spec
|
|
264
|
-
*/
|
|
265
|
-
function extractMaxFileSize(specContent) {
|
|
266
|
-
const match = specContent.match(/(\d+)\s*(mb|gb|kb)/i);
|
|
267
|
-
if (!match) return '10MB';
|
|
268
|
-
|
|
269
|
-
const size = parseInt(match[1]);
|
|
270
|
-
const unit = match[2].toLowerCase();
|
|
271
|
-
|
|
272
|
-
return `${size}${unit.toUpperCase()}`;
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
/**
|
|
276
|
-
* Extract allowed file types from spec
|
|
277
|
-
*/
|
|
278
|
-
function extractAllowedFileTypes(specContent) {
|
|
279
|
-
const match = specContent.match(/\.(jpg|jpeg|png|pdf|doc|docx|xls|xlsx|csv|txt|zip)(?:\s*,\s*\.|\s+)/gi);
|
|
280
|
-
if (!match) return ['.jpg', '.jpeg', '.png'];
|
|
281
|
-
|
|
282
|
-
return match.map(m => m.trim().replace(/\s*,\s*$/, ''));
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
/**
|
|
286
|
-
* Calculate confidence score
|
|
287
|
-
*/
|
|
288
|
-
function calculateConfidence(entities, crudOperations, uiKeywords) {
|
|
289
|
-
let score = 0;
|
|
290
|
-
|
|
291
|
-
// Entities detected
|
|
292
|
-
if (entities.length > 0) score += 30;
|
|
293
|
-
if (entities.length > 2) score += 10;
|
|
294
|
-
|
|
295
|
-
// CRUD operations
|
|
296
|
-
const crudCount = Object.values(crudOperations).filter(v => v).length;
|
|
297
|
-
score += crudCount * 10;
|
|
298
|
-
|
|
299
|
-
// UI keywords
|
|
300
|
-
if (uiKeywords.hasUIKeywords) score += 20;
|
|
301
|
-
if (uiKeywords.wizard) score += 15;
|
|
302
|
-
if (uiKeywords.dashboard) score += 15;
|
|
303
|
-
|
|
304
|
-
return Math.min(100, score);
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
/**
|
|
308
|
-
* Generate UI phase trigger message
|
|
309
|
-
*/
|
|
310
|
-
export function generateUITriggerMessage(analysis) {
|
|
311
|
-
if (!analysis.shouldTrigger) {
|
|
312
|
-
return null;
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
const { entities, crudOperations, uiNeeds, confidence } = analysis;
|
|
316
|
-
|
|
317
|
-
const parts = [];
|
|
318
|
-
|
|
319
|
-
parts.push(`🎨 **UI/UX Auto-Detection** (${confidence}% confidence)`);
|
|
320
|
-
parts.push('');
|
|
321
|
-
|
|
322
|
-
if (entities.length > 0) {
|
|
323
|
-
parts.push(`**Entities Detected:** ${entities.map(e => e.name).join(', ')}`);
|
|
324
|
-
}
|
|
325
|
-
|
|
326
|
-
if (Object.values(crudOperations).some(v => v)) {
|
|
327
|
-
const ops = Object.entries(crudOperations)
|
|
328
|
-
.filter(([k, v]) => v)
|
|
329
|
-
.map(([k]) => k.toUpperCase());
|
|
330
|
-
parts.push(`**CRUD Operations:** ${ops.join(', ')}`);
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
if (uiNeeds.length > 0) {
|
|
334
|
-
parts.push('');
|
|
335
|
-
parts.push('**UI Needs Detected:**');
|
|
336
|
-
uiNeeds.forEach((need, i) => {
|
|
337
|
-
const icon = need.type === 'form' ? '📝' :
|
|
338
|
-
need.type === 'list' ? '📋' :
|
|
339
|
-
need.type === 'wizard' ? '🧙' :
|
|
340
|
-
need.type === 'dashboard' ? '📊' : '🔧';
|
|
341
|
-
parts.push(`${i + 1}. ${icon} ${need.type.toUpperCase()}: ${need.entity || need.operation || 'Generic'}`);
|
|
342
|
-
});
|
|
343
|
-
}
|
|
344
|
-
|
|
345
|
-
parts.push('');
|
|
346
|
-
parts.push('**➡️ Auto-triggering FASE 1.5: UI/UX Design**');
|
|
347
|
-
parts.push('Generating wireframes, component specs, and design system...');
|
|
348
|
-
|
|
349
|
-
return parts.join('\n');
|
|
350
|
-
}
|
|
@@ -1,293 +0,0 @@
|
|
|
1
|
-
# MORPH-SPEC - Azure DevOps Pipelines
|
|
2
|
-
|
|
3
|
-
> **CI/CD para One-Person Business com Workload Identity Federation (sem secrets)**
|
|
4
|
-
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
## 🚀 Quick Start
|
|
8
|
-
|
|
9
|
-
### 1. Configurar Workload Identity (10 min)
|
|
10
|
-
|
|
11
|
-
```bash
|
|
12
|
-
# Ver guia completo em: docs/azure-devops-setup.md
|
|
13
|
-
|
|
14
|
-
# Criar App Registrations
|
|
15
|
-
az ad app create --display-name "myapp-staging-pipeline"
|
|
16
|
-
az ad app create --display-name "myapp-prod-pipeline"
|
|
17
|
-
|
|
18
|
-
# Configurar federated credentials
|
|
19
|
-
# (Ver guia detalhado)
|
|
20
|
-
```
|
|
21
|
-
|
|
22
|
-
### 2. Importar Pipelines no Azure DevOps
|
|
23
|
-
|
|
24
|
-
1. **Pipelines** → **New pipeline**
|
|
25
|
-
2. **Azure Repos Git** → Selecione repo
|
|
26
|
-
3. **Existing Azure Pipelines YAML file**
|
|
27
|
-
4. Selecione:
|
|
28
|
-
- `.azure/pipelines/staging-pipeline.yml`
|
|
29
|
-
- `.azure/pipelines/prod-pipeline.yml`
|
|
30
|
-
|
|
31
|
-
### 3. Configurar Variáveis
|
|
32
|
-
|
|
33
|
-
Para cada pipeline, adicione:
|
|
34
|
-
```
|
|
35
|
-
ACR_NAME: <seu-acr-name>
|
|
36
|
-
APP_NAME: <seu-app-name>
|
|
37
|
-
SUBSCRIPTION_ID: <subscription-id>
|
|
38
|
-
```
|
|
39
|
-
|
|
40
|
-
### 4. Criar Environments
|
|
41
|
-
|
|
42
|
-
1. **Pipelines** → **Environments** → **New environment**
|
|
43
|
-
2. Criar:
|
|
44
|
-
- `staging` (sem aprovação - deploy rápido)
|
|
45
|
-
- `production` (aprovação obrigatória)
|
|
46
|
-
|
|
47
|
-
### 5. Testar!
|
|
48
|
-
|
|
49
|
-
```bash
|
|
50
|
-
# Trigger staging pipeline
|
|
51
|
-
git checkout staging
|
|
52
|
-
git commit -m "test" --allow-empty
|
|
53
|
-
git push origin staging
|
|
54
|
-
|
|
55
|
-
# Trigger prod pipeline
|
|
56
|
-
git checkout main
|
|
57
|
-
git commit -m "test" --allow-empty
|
|
58
|
-
git push origin main
|
|
59
|
-
# ⏸️ Aprovar manualmente no Azure DevOps
|
|
60
|
-
```
|
|
61
|
-
|
|
62
|
-
---
|
|
63
|
-
|
|
64
|
-
## 📁 Estrutura
|
|
65
|
-
|
|
66
|
-
```
|
|
67
|
-
.azure/
|
|
68
|
-
├── README.md # Este arquivo
|
|
69
|
-
├── docs/
|
|
70
|
-
│ ├── azure-devops-setup.md # Guia completo de setup
|
|
71
|
-
│ ├── local-development.md # Como rodar projeto local
|
|
72
|
-
│ └── branch-strategy.md # Estratégia de branches
|
|
73
|
-
└── pipelines/
|
|
74
|
-
├── staging-pipeline.yml # Pipeline staging (branch: staging)
|
|
75
|
-
├── prod-pipeline.yml # Pipeline prod (branch: main/master)
|
|
76
|
-
├── pipeline-variables.yml # Variáveis compartilhadas
|
|
77
|
-
└── templates/
|
|
78
|
-
├── build-dotnet.yml # Template: Build .NET
|
|
79
|
-
├── deploy-app-service.yml # Template: Deploy App Service
|
|
80
|
-
├── deploy-container-app.yml # Template: Deploy Container Apps
|
|
81
|
-
└── infra-deploy.yml # Template: Deploy Bicep
|
|
82
|
-
```
|
|
83
|
-
|
|
84
|
-
---
|
|
85
|
-
|
|
86
|
-
## 🔄 Pipelines
|
|
87
|
-
|
|
88
|
-
### Staging Pipeline (`staging-pipeline.yml`)
|
|
89
|
-
|
|
90
|
-
**Hosting:** Container Apps com scale-to-zero (~$5-10/mês)
|
|
91
|
-
|
|
92
|
-
**Trigger:** Push em `staging` branch
|
|
93
|
-
|
|
94
|
-
**Stages:**
|
|
95
|
-
1. ✅ Build & Test
|
|
96
|
-
2. ✅ Deploy Infrastructure (Bicep)
|
|
97
|
-
3. ✅ Build Container Image
|
|
98
|
-
4. ✅ Push to ACR
|
|
99
|
-
5. ✅ Deploy Container App
|
|
100
|
-
6. ✅ Integration Tests
|
|
101
|
-
|
|
102
|
-
**Aprovação:** Nenhuma (deploy automático)
|
|
103
|
-
|
|
104
|
-
**Uso:** QA, testes de integração
|
|
105
|
-
|
|
106
|
-
---
|
|
107
|
-
|
|
108
|
-
### Prod Pipeline (`prod-pipeline.yml`)
|
|
109
|
-
|
|
110
|
-
**Hosting:** Container Apps always-on (~$10-20/mês)
|
|
111
|
-
|
|
112
|
-
**Trigger:** Push em `main` ou `master` branch
|
|
113
|
-
|
|
114
|
-
**Stages:**
|
|
115
|
-
1. ✅ Build & Test
|
|
116
|
-
2. ✅ Security Scan
|
|
117
|
-
3. ✅ Deploy Infrastructure (Bicep) ← **Approval Required**
|
|
118
|
-
4. ✅ Build Container Image
|
|
119
|
-
5. ✅ Security Scan (Image)
|
|
120
|
-
6. ✅ Deploy to Production ← **Approval Required**
|
|
121
|
-
7. ✅ Smoke Tests (Critical)
|
|
122
|
-
8. ✅ Monitor & Report
|
|
123
|
-
|
|
124
|
-
**Aprovação:** OBRIGATÓRIA (manual approval gate)
|
|
125
|
-
|
|
126
|
-
**Uso:** Produção, ambiente crítico
|
|
127
|
-
|
|
128
|
-
---
|
|
129
|
-
|
|
130
|
-
## 🌐 Desenvolvimento Local
|
|
131
|
-
|
|
132
|
-
**Developers NÃO têm ambiente próprio.** Ao invés disso:
|
|
133
|
-
|
|
134
|
-
- ✅ Rodam projeto **LOCAL** (Visual Studio/Rider/VS Code)
|
|
135
|
-
- ✅ Acessam recursos **REMOTOS** staging (SQL, Storage, Key Vault)
|
|
136
|
-
- ✅ Testam localmente antes de commitar
|
|
137
|
-
|
|
138
|
-
**Ver guia completo:** [`docs/local-development.md`](docs/local-development.md)
|
|
139
|
-
|
|
140
|
-
---
|
|
141
|
-
|
|
142
|
-
## 🎯 Fluxo Completo
|
|
143
|
-
|
|
144
|
-
### Desenvolvimento Diário
|
|
145
|
-
|
|
146
|
-
```bash
|
|
147
|
-
# 1. Criar feature branch
|
|
148
|
-
git checkout staging
|
|
149
|
-
git pull origin staging
|
|
150
|
-
git checkout -b feature/nova-funcionalidade
|
|
151
|
-
|
|
152
|
-
# 2. Desenvolver LOCAL
|
|
153
|
-
dotnet run # Conecta em recursos staging
|
|
154
|
-
|
|
155
|
-
# 3. Commitar
|
|
156
|
-
git add .
|
|
157
|
-
git commit -m "feat: adiciona nova funcionalidade"
|
|
158
|
-
git push origin feature/nova-funcionalidade
|
|
159
|
-
|
|
160
|
-
# 4. Criar PR para staging
|
|
161
|
-
# Azure DevOps → Repos → Pull Requests → New
|
|
162
|
-
# Source: feature/nova-funcionalidade → Target: staging
|
|
163
|
-
# Self-approve e merge
|
|
164
|
-
|
|
165
|
-
# 5. Staging pipeline triggado automaticamente
|
|
166
|
-
# ✅ Deploy para staging
|
|
167
|
-
```
|
|
168
|
-
|
|
169
|
-
### Release para Produção
|
|
170
|
-
|
|
171
|
-
```bash
|
|
172
|
-
# 1. Criar PR staging → main
|
|
173
|
-
# Azure DevOps → Repos → Pull Requests → New
|
|
174
|
-
# Source: staging → Target: main
|
|
175
|
-
|
|
176
|
-
# 2. Self-review e merge
|
|
177
|
-
|
|
178
|
-
# 3. Prod pipeline triggado
|
|
179
|
-
# ⏸️ Approval gate aparece
|
|
180
|
-
# Revisar deployment summary
|
|
181
|
-
# Aprovar manualmente
|
|
182
|
-
|
|
183
|
-
# 4. Deploy para produção
|
|
184
|
-
# ✅ Aplicação em produção
|
|
185
|
-
```
|
|
186
|
-
|
|
187
|
-
---
|
|
188
|
-
|
|
189
|
-
## 📊 Comparativo de Ambientes
|
|
190
|
-
|
|
191
|
-
| Aspecto | Staging | Prod |
|
|
192
|
-
|---------|---------|------|
|
|
193
|
-
| **Hosting** | Container Apps | Container Apps |
|
|
194
|
-
| **Custo** | $5-10/mês | $10-20/mês |
|
|
195
|
-
| **Disponibilidade** | Scale-to-zero | Always-on (min 1) |
|
|
196
|
-
| **SSL** | Custom domain OK | Custom domain OK |
|
|
197
|
-
| **Auto-scaling** | ✅ Sim | ✅ Sim |
|
|
198
|
-
| **Trigger** | Push to `staging` | Push to `main` |
|
|
199
|
-
| **Aprovação** | Nenhuma | **Obrigatória** |
|
|
200
|
-
| **Tests** | Unit + Integration | Unit + Integration + Security |
|
|
201
|
-
|
|
202
|
-
---
|
|
203
|
-
|
|
204
|
-
## 🔐 Workload Identity Federation
|
|
205
|
-
|
|
206
|
-
### O que é?
|
|
207
|
-
|
|
208
|
-
Autenticação moderna do Azure DevOps para Azure **sem usar secrets/passwords**.
|
|
209
|
-
|
|
210
|
-
### Vantagens
|
|
211
|
-
|
|
212
|
-
| Tradicional (Service Principal) | Workload Identity |
|
|
213
|
-
|--------------------------------|-------------------|
|
|
214
|
-
| ❌ Secrets expiram (1-2 anos) | ✅ Token auto-renova |
|
|
215
|
-
| ❌ Secrets vazam facilmente | ✅ Sem secrets armazenados |
|
|
216
|
-
| ❌ Rotação manual | ✅ Rotação automática |
|
|
217
|
-
| ❌ Dificil auditar | ✅ Audit trail completo |
|
|
218
|
-
|
|
219
|
-
### Setup
|
|
220
|
-
|
|
221
|
-
Ver guia completo: [`docs/azure-devops-setup.md`](docs/azure-devops-setup.md)
|
|
222
|
-
|
|
223
|
-
---
|
|
224
|
-
|
|
225
|
-
## 🆘 Troubleshooting
|
|
226
|
-
|
|
227
|
-
### Pipeline falha com "Failed to get federated token"
|
|
228
|
-
|
|
229
|
-
**Causa:** Federated credential não configurado corretamente.
|
|
230
|
-
|
|
231
|
-
**Solução:**
|
|
232
|
-
1. Verificar subject do federated credential
|
|
233
|
-
2. Deve ser: `sc://<ORG>/<PROJECT>/<SERVICE_CONNECTION_NAME>`
|
|
234
|
-
3. Recriar se necessário (ver `docs/azure-devops-setup.md`)
|
|
235
|
-
|
|
236
|
-
### Pipeline falha com "Insufficient permissions"
|
|
237
|
-
|
|
238
|
-
**Causa:** Service Principal não tem permissões.
|
|
239
|
-
|
|
240
|
-
**Solução:**
|
|
241
|
-
```bash
|
|
242
|
-
# Adicionar Contributor role
|
|
243
|
-
az role assignment create \
|
|
244
|
-
--assignee <SP_ID> \
|
|
245
|
-
--role Contributor \
|
|
246
|
-
--scope "/subscriptions/<SUB_ID>/resourceGroups/<RG_NAME>"
|
|
247
|
-
```
|
|
248
|
-
|
|
249
|
-
### Container não sobe após deploy
|
|
250
|
-
|
|
251
|
-
**Causa:** Possíveis: imagem incorreta, health check falhando, ACR permissions.
|
|
252
|
-
|
|
253
|
-
**Solução:**
|
|
254
|
-
```bash
|
|
255
|
-
# Ver logs do Container App
|
|
256
|
-
az containerapp logs show \
|
|
257
|
-
-n ca-myapp-staging \
|
|
258
|
-
-g rg-myapp-staging \
|
|
259
|
-
--follow
|
|
260
|
-
```
|
|
261
|
-
|
|
262
|
-
---
|
|
263
|
-
|
|
264
|
-
## 📚 Documentação Completa
|
|
265
|
-
|
|
266
|
-
| Documento | Descrição |
|
|
267
|
-
|-----------|-----------|
|
|
268
|
-
| [Azure DevOps Setup](docs/azure-devops-setup.md) | Setup completo (Workload Identity, Service Connections, Environments) |
|
|
269
|
-
| [Local Development](docs/local-development.md) | Como rodar projeto local e acessar recursos staging |
|
|
270
|
-
| [Branch Strategy](docs/branch-strategy.md) | Estratégia de branches (staging/main, feature branches) |
|
|
271
|
-
| [Migration Guide](../.morph/standards/migration-guide.md) | App Service → Container Apps + CI/CD |
|
|
272
|
-
| [Azure Standards](../.morph/standards/azure.md) | Padrões Azure e IaC |
|
|
273
|
-
|
|
274
|
-
---
|
|
275
|
-
|
|
276
|
-
## ✅ Checklist de Produção
|
|
277
|
-
|
|
278
|
-
Antes de ir para produção:
|
|
279
|
-
|
|
280
|
-
- [ ] Workload Identity configurada (staging/prod)
|
|
281
|
-
- [ ] Service connections criadas e testadas
|
|
282
|
-
- [ ] Variáveis configuradas (ACR_NAME, APP_NAME, SUBSCRIPTION_ID)
|
|
283
|
-
- [ ] Environments criados (staging sem aprovação, prod com aprovação)
|
|
284
|
-
- [ ] Staging pipeline testado com sucesso
|
|
285
|
-
- [ ] Prod pipeline testado com aprovação
|
|
286
|
-
- [ ] Health checks implementados e funcionando
|
|
287
|
-
- [ ] Application Insights configurado
|
|
288
|
-
- [ ] Alerts configurados (CPU, Memory, Availability)
|
|
289
|
-
- [ ] Runbook de rollback documentado
|
|
290
|
-
|
|
291
|
-
---
|
|
292
|
-
|
|
293
|
-
*MORPH-SPEC by Polymorphism Tech*
|