@polymorphism-tech/morph-spec 3.0.1 → 3.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 +561 -63
- package/LICENSE +72 -72
- package/README.md +275 -79
- package/bin/detect-agents.js +3 -1
- package/bin/morph-spec.js +60 -1
- package/bin/render-template.js +61 -14
- package/bin/semantic-detect-agents.js +2 -1
- package/bin/{task-manager.js → task-manager.cjs} +113 -8
- package/bin/validate-agents-skills.js +10 -4
- package/bin/validate-agents.js +4 -3
- package/docs/api/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.svg +977 -977
- package/docs/api/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.svg +1048 -1048
- package/docs/api/scripts/collapse.js +38 -38
- package/docs/api/scripts/commonNav.js +28 -28
- package/docs/api/scripts/linenumber.js +25 -25
- package/docs/api/scripts/nav.js +12 -12
- package/docs/api/scripts/polyfill.js +3 -3
- package/docs/api/scripts/prettify/Apache-License-2.0.txt +202 -202
- package/docs/api/scripts/prettify/lang-css.js +2 -2
- package/docs/api/scripts/prettify/prettify.js +28 -28
- package/docs/api/scripts/search.js +98 -98
- package/docs/api/styles/jsdoc.css +776 -776
- package/docs/api/styles/prettify.css +80 -80
- package/docs/cli-auto-detection.md +219 -0
- package/docs/examples.md +328 -328
- package/docs/getting-started.md +3 -3
- package/docs/llm-interaction-config.md +735 -0
- package/docs/templates.md +418 -418
- package/docs/troubleshooting.md +269 -0
- package/package.json +7 -3
- package/scripts/postinstall.js +132 -132
- package/scripts/reorganize-skills.cjs +1 -1
- package/scripts/validate-agents-structure.cjs +1 -1
- package/scripts/validate-skills.cjs +2 -2
- package/src/commands/advance-phase.js +93 -2
- package/src/commands/analyze-blazor-concurrency.js +193 -193
- package/src/commands/approve.js +221 -0
- package/src/commands/capture-pattern.js +121 -0
- package/src/commands/create-story.js +5 -2
- package/src/commands/deploy.js +780 -780
- package/src/commands/detect-agents.js +4 -2
- package/src/commands/generate.js +276 -149
- package/src/commands/init.js +37 -0
- package/src/commands/lint-fluent.js +352 -352
- package/src/commands/migrate-state.js +158 -0
- package/src/commands/rollback-phase.js +185 -185
- package/src/commands/search-patterns.js +126 -0
- package/src/commands/session-summary.js +291 -291
- package/src/commands/shard-spec.js +224 -224
- package/src/commands/spawn-team.js +172 -0
- package/src/commands/sprint-status.js +250 -250
- package/src/commands/task.js +3 -3
- package/src/commands/troubleshoot.js +222 -222
- package/src/commands/update.js +36 -0
- package/src/commands/upgrade.js +346 -0
- package/src/commands/validate-blazor-state.js +210 -210
- package/src/commands/validate-blazor.js +156 -156
- package/src/commands/validate-css.js +84 -84
- package/src/commands/validate-phase.js +221 -221
- package/src/generator/.gitkeep +0 -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/blazor-concurrency-analyzer.js +288 -288
- package/src/lib/blazor-state-validator.js +291 -291
- package/src/lib/blazor-validator.js +374 -374
- package/src/lib/checkpoint-hooks.js +258 -0
- package/src/lib/context-generator.js +7 -4
- package/src/lib/css-validator.js +352 -352
- package/src/lib/design-system-generator.js +298 -298
- package/src/lib/hook-executor.js +2 -1
- package/src/lib/learning-system.js +520 -520
- package/src/lib/metadata-extractor.js +380 -0
- package/src/lib/mockup-generator.js +366 -366
- package/src/lib/phase-state-machine.js +214 -0
- package/src/lib/stack-resolver.js +148 -0
- package/src/lib/standards-context-injector.js +4 -3
- package/src/lib/state-manager.js +120 -0
- package/src/lib/team-orchestrator.js +2 -1
- package/src/lib/template-data-sources.js +325 -0
- package/src/lib/troubleshoot-grep.js +204 -194
- package/src/lib/troubleshoot-index.js +144 -144
- package/src/lib/ui-detector.js +350 -350
- package/src/lib/validation-runner.js +2 -1
- package/src/lib/validators/architecture-validator.js +387 -387
- package/src/lib/validators/content-validator.js +351 -0
- package/src/lib/validators/package-validator.js +360 -360
- package/src/lib/validators/ui-contrast-validator.js +422 -422
- package/src/llm/.gitkeep +0 -0
- 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/llm/schema-validator.js +121 -0
- package/src/orchestrator.js +206 -0
- package/src/sanitizer/.gitkeep +0 -0
- package/src/sanitizer/context-sanitizer.js +221 -0
- package/src/sanitizer/patterns.js +163 -0
- package/src/scanner/.gitkeep +0 -0
- package/src/scanner/project-scanner.js +242 -0
- package/src/types/index.js +477 -0
- package/src/ui/.gitkeep +0 -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 +190 -0
- package/src/utils/file-copier.js +3 -1
- package/src/utils/logger.js +32 -32
- package/src/utils/version-checker.js +175 -175
- package/src/writer/.gitkeep +0 -0
- package/src/writer/file-writer.js +86 -0
- package/{content → stacks/blazor-azure}/.azure/README.md +2 -2
- package/{content → stacks/blazor-azure}/.azure/pipelines/pipeline-variables.yml +1 -1
- package/{content → stacks/blazor-azure}/.azure/pipelines/prod-pipeline.yml +1 -1
- package/{content → stacks/blazor-azure}/.azure/pipelines/staging-pipeline.yml +1 -1
- package/{content → stacks/blazor-azure}/.claude/commands/morph-preflight.md +227 -227
- package/{content → stacks/blazor-azure}/.claude/commands/morph-troubleshoot.md +122 -122
- package/{content → stacks/blazor-azure}/.claude/skills/level-1-workflows/phase-setup.md +1 -1
- package/{content → stacks/blazor-azure}/.morph/docs/workflows/enforcement-pipeline.md +3 -3
- package/{content → stacks/blazor-azure}/.morph/hooks/README.md +12 -12
- package/{content → stacks/blazor-azure}/.morph/standards/agent-teams-workflow.md +2 -2
- package/{content → stacks/blazor-azure}/.morph/standards/migration-guide.md +2 -2
- package/{content → stacks/blazor-azure}/.morph/templates/infra/deploy-checklist.md +426 -426
- package/stacks/nextjs-supabase/.claude/skills/level-2-domains/backend/dotnet-supabase.md +244 -0
- package/stacks/nextjs-supabase/.claude/skills/level-2-domains/frontend/nextjs-supabase.md +335 -0
- package/stacks/nextjs-supabase/.claude/skills/level-2-domains/infrastructure/easypanel-deployer.md +189 -0
- package/stacks/nextjs-supabase/.claude/skills/level-2-domains/integrations/supabase-expert.md +170 -0
- package/stacks/nextjs-supabase/.morph/config/agents.json +345 -0
- package/stacks/nextjs-supabase/.morph/config/config.template.json +92 -0
- package/stacks/nextjs-supabase/.morph/docs/easypanel-setup.md +169 -0
- package/stacks/nextjs-supabase/.morph/docs/supabase-mcp-setup.md +247 -0
- package/stacks/nextjs-supabase/.morph/examples/crud-nextjs-supabase/README.md +697 -0
- package/stacks/nextjs-supabase/.morph/examples/crud-nextjs-supabase/spec.md +85 -0
- package/stacks/nextjs-supabase/.morph/examples/crud-nextjs-supabase/tasks.md +86 -0
- package/stacks/nextjs-supabase/.morph/examples/saas-nextjs-supabase/README.md +498 -0
- package/stacks/nextjs-supabase/.morph/examples/saas-nextjs-supabase/decisions.md +121 -0
- package/stacks/nextjs-supabase/.morph/examples/saas-nextjs-supabase/spec.md +138 -0
- package/stacks/nextjs-supabase/.morph/examples/saas-nextjs-supabase/tasks.md +162 -0
- package/stacks/nextjs-supabase/.morph/project.md +168 -0
- package/stacks/nextjs-supabase/.morph/standards/easypanel-deploy.md +191 -0
- package/stacks/nextjs-supabase/.morph/standards/nextjs-patterns.md +193 -0
- package/stacks/nextjs-supabase/.morph/standards/supabase-auth.md +171 -0
- package/stacks/nextjs-supabase/.morph/standards/supabase-pgvector.md +164 -0
- package/stacks/nextjs-supabase/.morph/standards/supabase-rls.md +179 -0
- package/stacks/nextjs-supabase/.morph/standards/supabase-storage.md +148 -0
- package/stacks/nextjs-supabase/.morph/templates/contracts.cs +173 -0
- package/stacks/nextjs-supabase/.morph/templates/contracts.ts +168 -0
- package/stacks/nextjs-supabase/.morph/templates/decisions.md +115 -0
- package/stacks/nextjs-supabase/.morph/templates/dockerfile-api.dockerfile +38 -0
- package/stacks/nextjs-supabase/.morph/templates/dockerfile-web.dockerfile +48 -0
- package/stacks/nextjs-supabase/.morph/templates/proposal.md +145 -0
- package/stacks/nextjs-supabase/.morph/templates/recap.md +134 -0
- package/stacks/nextjs-supabase/.morph/templates/rls-policy.sql +57 -0
- package/stacks/nextjs-supabase/.morph/templates/spec.md +231 -0
- package/stacks/nextjs-supabase/.morph/templates/supabase-migration.sql +100 -0
- package/stacks/nextjs-supabase/.morph/templates/tasks.md +257 -0
- package/stacks/nextjs-supabase/CLAUDE.md +149 -0
- package/stacks/nextjs-supabase/README.md +112 -0
- /package/{content → stacks/blazor-azure}/.azure/docs/azure-devops-setup.md +0 -0
- /package/{content → stacks/blazor-azure}/.azure/docs/branch-strategy.md +0 -0
- /package/{content → stacks/blazor-azure}/.azure/docs/local-development.md +0 -0
- /package/{content → stacks/blazor-azure}/.azure/pipelines/templates/build-dotnet.yml +0 -0
- /package/{content → stacks/blazor-azure}/.azure/pipelines/templates/deploy-app-service.yml +0 -0
- /package/{content → stacks/blazor-azure}/.azure/pipelines/templates/deploy-container-app.yml +0 -0
- /package/{content → stacks/blazor-azure}/.azure/pipelines/templates/infra-deploy.yml +0 -0
- /package/{content → stacks/blazor-azure}/.claude/commands/morph-apply.md +0 -0
- /package/{content → stacks/blazor-azure}/.claude/commands/morph-archive.md +0 -0
- /package/{content → stacks/blazor-azure}/.claude/commands/morph-deploy.md +0 -0
- /package/{content → stacks/blazor-azure}/.claude/commands/morph-infra.md +0 -0
- /package/{content → stacks/blazor-azure}/.claude/commands/morph-proposal.md +0 -0
- /package/{content → stacks/blazor-azure}/.claude/commands/morph-status.md +0 -0
- /package/{content → stacks/blazor-azure}/.claude/settings.local.json +0 -0
- /package/{content → stacks/blazor-azure}/.claude/skills/level-0-meta/README.md +0 -0
- /package/{content → stacks/blazor-azure}/.claude/skills/level-0-meta/code-review.md +0 -0
- /package/{content → stacks/blazor-azure}/.claude/skills/level-0-meta/morph-checklist.md +0 -0
- /package/{content → stacks/blazor-azure}/.claude/skills/level-0-meta/simulation-checklist.md +0 -0
- /package/{content → stacks/blazor-azure}/.claude/skills/level-1-workflows/README.md +0 -0
- /package/{content → stacks/blazor-azure}/.claude/skills/level-1-workflows/morph-replicate.md +0 -0
- /package/{content → stacks/blazor-azure}/.claude/skills/level-1-workflows/phase-clarify.md +0 -0
- /package/{content → stacks/blazor-azure}/.claude/skills/level-1-workflows/phase-design.md +0 -0
- /package/{content → stacks/blazor-azure}/.claude/skills/level-1-workflows/phase-tasks.md +0 -0
- /package/{content → stacks/blazor-azure}/.claude/skills/level-1-workflows/phase-uiux.md +0 -0
- /package/{content → stacks/blazor-azure}/.claude/skills/level-2-domains/README.md +0 -0
- /package/{content → stacks/blazor-azure}/.claude/skills/level-2-domains/ai-agents/ai-system-architect.md +0 -0
- /package/{content → stacks/blazor-azure}/.claude/skills/level-2-domains/architecture/po-pm-advisor.md +0 -0
- /package/{content → stacks/blazor-azure}/.claude/skills/level-2-domains/architecture/prompt-engineer.md +0 -0
- /package/{content → stacks/blazor-azure}/.claude/skills/level-2-domains/architecture/seo-growth-hacker.md +0 -0
- /package/{content → stacks/blazor-azure}/.claude/skills/level-2-domains/architecture/standards-architect.md +0 -0
- /package/{content → stacks/blazor-azure}/.claude/skills/level-2-domains/backend/dotnet-senior.md +0 -0
- /package/{content → stacks/blazor-azure}/.claude/skills/level-2-domains/backend/ef-modeler.md +0 -0
- /package/{content → stacks/blazor-azure}/.claude/skills/level-2-domains/backend/hangfire-orchestrator.md +0 -0
- /package/{content → stacks/blazor-azure}/.claude/skills/level-2-domains/backend/ms-agent-expert.md +0 -0
- /package/{content → stacks/blazor-azure}/.claude/skills/level-2-domains/frontend/blazor-builder.md +0 -0
- /package/{content → stacks/blazor-azure}/.claude/skills/level-2-domains/frontend/nextjs-expert.md +0 -0
- /package/{content → stacks/blazor-azure}/.claude/skills/level-2-domains/frontend/ui-ux-designer.md +0 -0
- /package/{content → stacks/blazor-azure}/.claude/skills/level-2-domains/infrastructure/azure-architect.md +0 -0
- /package/{content → stacks/blazor-azure}/.claude/skills/level-2-domains/infrastructure/azure-deploy-specialist.md +0 -0
- /package/{content → stacks/blazor-azure}/.claude/skills/level-2-domains/infrastructure/bicep-architect.md +0 -0
- /package/{content → stacks/blazor-azure}/.claude/skills/level-2-domains/infrastructure/container-specialist.md +0 -0
- /package/{content → stacks/blazor-azure}/.claude/skills/level-2-domains/infrastructure/devops-engineer.md +0 -0
- /package/{content → stacks/blazor-azure}/.claude/skills/level-2-domains/integrations/asaas-financial.md +0 -0
- /package/{content → stacks/blazor-azure}/.claude/skills/level-2-domains/integrations/azure-identity.md +0 -0
- /package/{content → stacks/blazor-azure}/.claude/skills/level-2-domains/integrations/clerk-auth.md +0 -0
- /package/{content → stacks/blazor-azure}/.claude/skills/level-2-domains/integrations/resend-email.md +0 -0
- /package/{content → stacks/blazor-azure}/.claude/skills/level-2-domains/quality/code-analyzer.md +0 -0
- /package/{content → stacks/blazor-azure}/.claude/skills/level-2-domains/quality/testing-specialist.md +0 -0
- /package/{content → stacks/blazor-azure}/.claude/skills/level-3-technologies/README.md +0 -0
- /package/{content → stacks/blazor-azure}/.claude/skills/level-4-patterns/README.md +0 -0
- /package/{content → stacks/blazor-azure}/.morph/.morphversion +0 -0
- /package/{content → stacks/blazor-azure}/.morph/archive/.gitkeep +0 -0
- /package/{content → stacks/blazor-azure}/.morph/config/agents.json +0 -0
- /package/{content → stacks/blazor-azure}/.morph/config/config.template.json +0 -0
- /package/{content → stacks/blazor-azure}/.morph/docs/STORY-DRIVEN-DEVELOPMENT.md +0 -0
- /package/{content → stacks/blazor-azure}/.morph/docs/workflows/design-impl.md +0 -0
- /package/{content → stacks/blazor-azure}/.morph/docs/workflows/fast-track.md +0 -0
- /package/{content → stacks/blazor-azure}/.morph/docs/workflows/full-morph.md +0 -0
- /package/{content → stacks/blazor-azure}/.morph/docs/workflows/standard.md +0 -0
- /package/{content → stacks/blazor-azure}/.morph/docs/workflows/ui-refresh.md +0 -0
- /package/{content → stacks/blazor-azure}/.morph/examples/api-nextjs/README.md +0 -0
- /package/{content → stacks/blazor-azure}/.morph/examples/api-nextjs/contracts.ts +0 -0
- /package/{content → stacks/blazor-azure}/.morph/examples/api-nextjs/spec.md +0 -0
- /package/{content → stacks/blazor-azure}/.morph/examples/api-nextjs/tasks.md +0 -0
- /package/{content → stacks/blazor-azure}/.morph/examples/micro-saas/README.md +0 -0
- /package/{content → stacks/blazor-azure}/.morph/examples/micro-saas/contracts.cs +0 -0
- /package/{content → stacks/blazor-azure}/.morph/examples/micro-saas/decisions.md +0 -0
- /package/{content → stacks/blazor-azure}/.morph/examples/micro-saas/spec.md +0 -0
- /package/{content → stacks/blazor-azure}/.morph/examples/micro-saas/tasks.md +0 -0
- /package/{content → stacks/blazor-azure}/.morph/examples/multi-agent/README.md +0 -0
- /package/{content → stacks/blazor-azure}/.morph/examples/multi-agent/contracts.cs +0 -0
- /package/{content → stacks/blazor-azure}/.morph/examples/multi-agent/spec.md +0 -0
- /package/{content → stacks/blazor-azure}/.morph/examples/multi-agent/tasks.md +0 -0
- /package/{content → stacks/blazor-azure}/.morph/examples/scheduled-reports/decisions.md +0 -0
- /package/{content → stacks/blazor-azure}/.morph/examples/scheduled-reports/proposal.md +0 -0
- /package/{content → stacks/blazor-azure}/.morph/examples/scheduled-reports/spec.md +0 -0
- /package/{content → stacks/blazor-azure}/.morph/examples/state-v3.json +0 -0
- /package/{content → stacks/blazor-azure}/.morph/features/.gitkeep +0 -0
- /package/{content → stacks/blazor-azure}/.morph/hooks/pre-commit-agents.sh +0 -0
- /package/{content → stacks/blazor-azure}/.morph/hooks/pre-commit-all.sh +0 -0
- /package/{content → stacks/blazor-azure}/.morph/hooks/pre-commit-specs.sh +0 -0
- /package/{content → stacks/blazor-azure}/.morph/hooks/pre-commit-tests.sh +0 -0
- /package/{content → stacks/blazor-azure}/.morph/hooks/task-completed.js +0 -0
- /package/{content → stacks/blazor-azure}/.morph/hooks/teammate-idle.js +0 -0
- /package/{content → stacks/blazor-azure}/.morph/project.md +0 -0
- /package/{content → stacks/blazor-azure}/.morph/schemas/agent.schema.json +0 -0
- /package/{content → stacks/blazor-azure}/.morph/schemas/tasks.schema.json +0 -0
- /package/{content → stacks/blazor-azure}/.morph/specs/.gitkeep +0 -0
- /package/{content → stacks/blazor-azure}/.morph/standards/agent-framework-blazor-ui.md +0 -0
- /package/{content → stacks/blazor-azure}/.morph/standards/agent-framework-production.md +0 -0
- /package/{content → stacks/blazor-azure}/.morph/standards/agent-framework-setup.md +0 -0
- /package/{content → stacks/blazor-azure}/.morph/standards/agent-framework-workflows.md +0 -0
- /package/{content → stacks/blazor-azure}/.morph/standards/architecture.md +0 -0
- /package/{content → stacks/blazor-azure}/.morph/standards/azure.md +0 -0
- /package/{content → stacks/blazor-azure}/.morph/standards/coding.md +0 -0
- /package/{content → stacks/blazor-azure}/.morph/standards/dotnet10-migration.md +0 -0
- /package/{content → stacks/blazor-azure}/.morph/standards/fluent-ui-setup.md +0 -0
- /package/{content → stacks/blazor-azure}/.morph/standards/passkeys-auth.md +0 -0
- /package/{content → stacks/blazor-azure}/.morph/standards/vector-search-rag.md +0 -0
- /package/{content → stacks/blazor-azure}/.morph/state.json +0 -0
- /package/{content → stacks/blazor-azure}/.morph/templates/CONTEXT-FEATURE.md +0 -0
- /package/{content → stacks/blazor-azure}/.morph/templates/CONTEXT.md +0 -0
- /package/{content → stacks/blazor-azure}/.morph/templates/FluentDesignTheme.cs +0 -0
- /package/{content → stacks/blazor-azure}/.morph/templates/MudTheme.cs +0 -0
- /package/{content → stacks/blazor-azure}/.morph/templates/agent.cs +0 -0
- /package/{content → stacks/blazor-azure}/.morph/templates/clarify-questions.md +0 -0
- /package/{content → stacks/blazor-azure}/.morph/templates/component.razor +0 -0
- /package/{content → stacks/blazor-azure}/.morph/templates/contracts/Commands.cs +0 -0
- /package/{content → stacks/blazor-azure}/.morph/templates/contracts/Entities.cs +0 -0
- /package/{content → stacks/blazor-azure}/.morph/templates/contracts/Queries.cs +0 -0
- /package/{content → stacks/blazor-azure}/.morph/templates/contracts/README.md +0 -0
- /package/{content → stacks/blazor-azure}/.morph/templates/contracts.cs +0 -0
- /package/{content → stacks/blazor-azure}/.morph/templates/decisions.md +0 -0
- /package/{content → stacks/blazor-azure}/.morph/templates/design-system.css +0 -0
- /package/{content → stacks/blazor-azure}/.morph/templates/infra/.dockerignore.example +0 -0
- /package/{content → stacks/blazor-azure}/.morph/templates/infra/Dockerfile.example +0 -0
- /package/{content → stacks/blazor-azure}/.morph/templates/infra/README.md +0 -0
- /package/{content → stacks/blazor-azure}/.morph/templates/infra/app-insights.bicep +0 -0
- /package/{content → stacks/blazor-azure}/.morph/templates/infra/app-service.bicep +0 -0
- /package/{content → stacks/blazor-azure}/.morph/templates/infra/azure-pipelines-deploy.yml +0 -0
- /package/{content → stacks/blazor-azure}/.morph/templates/infra/container-app-env.bicep +0 -0
- /package/{content → stacks/blazor-azure}/.morph/templates/infra/container-app.bicep +0 -0
- /package/{content → stacks/blazor-azure}/.morph/templates/infra/deploy.ps1 +0 -0
- /package/{content → stacks/blazor-azure}/.morph/templates/infra/deploy.sh +0 -0
- /package/{content → stacks/blazor-azure}/.morph/templates/infra/key-vault.bicep +0 -0
- /package/{content → stacks/blazor-azure}/.morph/templates/infra/main.bicep +0 -0
- /package/{content → stacks/blazor-azure}/.morph/templates/infra/parameters.dev.json +0 -0
- /package/{content → stacks/blazor-azure}/.morph/templates/infra/parameters.prod.json +0 -0
- /package/{content → stacks/blazor-azure}/.morph/templates/infra/parameters.staging.json +0 -0
- /package/{content → stacks/blazor-azure}/.morph/templates/infra/sql-database.bicep +0 -0
- /package/{content → stacks/blazor-azure}/.morph/templates/infra/storage.bicep +0 -0
- /package/{content → stacks/blazor-azure}/.morph/templates/integrations/asaas-client.cs +0 -0
- /package/{content → stacks/blazor-azure}/.morph/templates/integrations/asaas-webhook.cs +0 -0
- /package/{content → stacks/blazor-azure}/.morph/templates/integrations/azure-identity-config.cs +0 -0
- /package/{content → stacks/blazor-azure}/.morph/templates/integrations/clerk-config.cs +0 -0
- /package/{content → stacks/blazor-azure}/.morph/templates/job.cs +0 -0
- /package/{content → stacks/blazor-azure}/.morph/templates/migration.cs +0 -0
- /package/{content → stacks/blazor-azure}/.morph/templates/proposal.md +0 -0
- /package/{content → stacks/blazor-azure}/.morph/templates/recap.md +0 -0
- /package/{content → stacks/blazor-azure}/.morph/templates/repository.cs +0 -0
- /package/{content → stacks/blazor-azure}/.morph/templates/saas/subscription.cs +0 -0
- /package/{content → stacks/blazor-azure}/.morph/templates/saas/tenant.cs +0 -0
- /package/{content → stacks/blazor-azure}/.morph/templates/service.cs +0 -0
- /package/{content → stacks/blazor-azure}/.morph/templates/simulation.md +0 -0
- /package/{content → stacks/blazor-azure}/.morph/templates/spec.md +0 -0
- /package/{content → stacks/blazor-azure}/.morph/templates/sprint-status.yaml +0 -0
- /package/{content → stacks/blazor-azure}/.morph/templates/state.template.json +0 -0
- /package/{content → stacks/blazor-azure}/.morph/templates/story.md +0 -0
- /package/{content → stacks/blazor-azure}/.morph/templates/tasks.md +0 -0
- /package/{content → stacks/blazor-azure}/.morph/templates/test.cs +0 -0
- /package/{content → stacks/blazor-azure}/.morph/templates/ui-components.md +0 -0
- /package/{content → stacks/blazor-azure}/.morph/templates/ui-design-system.md +0 -0
- /package/{content → stacks/blazor-azure}/.morph/templates/ui-flows.md +0 -0
- /package/{content → stacks/blazor-azure}/.morph/templates/ui-mockups.md +0 -0
- /package/{content → stacks/blazor-azure}/.morph/test-infra/example.bicep +0 -0
- /package/{content → stacks/blazor-azure}/CLAUDE.md +0 -0
- /package/{content → stacks/blazor-azure}/README.md +0 -0
|
@@ -1,224 +1,224 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* MORPH-SPEC Document Sharding
|
|
3
|
-
* Splits large spec.md files into manageable shards (BMAD-inspired)
|
|
4
|
-
* Achieves 90% token savings by loading only relevant sections
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import fs from 'fs';
|
|
8
|
-
import path from 'path';
|
|
9
|
-
import ora from 'ora';
|
|
10
|
-
import chalk from 'chalk';
|
|
11
|
-
import { logger } from '../utils/logger.js';
|
|
12
|
-
import { ensureDir, writeFile } from '../utils/file-copier.js';
|
|
13
|
-
|
|
14
|
-
// ============================================================================
|
|
15
|
-
// Helper Functions
|
|
16
|
-
// ============================================================================
|
|
17
|
-
|
|
18
|
-
function parseSpec(specContent) {
|
|
19
|
-
const sections = [];
|
|
20
|
-
const lines = specContent.split('\n');
|
|
21
|
-
|
|
22
|
-
let currentSection = null;
|
|
23
|
-
let currentContent = [];
|
|
24
|
-
|
|
25
|
-
for (const line of lines) {
|
|
26
|
-
// Detect level 2 heading (## Heading)
|
|
27
|
-
if (line.match(/^## /)) {
|
|
28
|
-
// Save previous section
|
|
29
|
-
if (currentSection) {
|
|
30
|
-
sections.push({
|
|
31
|
-
title: currentSection,
|
|
32
|
-
slug: toSlug(currentSection),
|
|
33
|
-
content: currentContent.join('\n').trim(),
|
|
34
|
-
});
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
// Start new section
|
|
38
|
-
currentSection = line.replace(/^## /, '').trim();
|
|
39
|
-
currentContent = [line]; // Include heading in content
|
|
40
|
-
} else {
|
|
41
|
-
currentContent.push(line);
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
// Save last section
|
|
46
|
-
if (currentSection) {
|
|
47
|
-
sections.push({
|
|
48
|
-
title: currentSection,
|
|
49
|
-
slug: toSlug(currentSection),
|
|
50
|
-
content: currentContent.join('\n').trim(),
|
|
51
|
-
});
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
return sections;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
function toSlug(title) {
|
|
58
|
-
return title
|
|
59
|
-
.toLowerCase()
|
|
60
|
-
.replace(/[^a-z0-9]+/g, '-')
|
|
61
|
-
.replace(/^-|-$/g, '');
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
function generateIndex(sections, featureName) {
|
|
65
|
-
let index = `# ${toTitleCase(featureName)} - Technical Specification\n\n`;
|
|
66
|
-
index += `> **Sharded Spec:** This spec has been split into sections for optimal token usage\n`;
|
|
67
|
-
index += `> **BMAD Pattern:** Load only the section you need during implementation\n\n`;
|
|
68
|
-
index += `---\n\n`;
|
|
69
|
-
index += `## 📋 Table of Contents\n\n`;
|
|
70
|
-
|
|
71
|
-
sections.forEach((section, i) => {
|
|
72
|
-
index += `${i + 1}. **[${section.title}](${section.slug}.md)**\n`;
|
|
73
|
-
|
|
74
|
-
// Add first 100 chars as description
|
|
75
|
-
const firstLine = section.content.split('\n').find(l => l.trim() && !l.startsWith('#'));
|
|
76
|
-
const description = firstLine ? firstLine.substring(0, 100) + '...' : 'See section for details';
|
|
77
|
-
index += ` > ${description}\n\n`;
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
index += `---\n\n`;
|
|
81
|
-
index += `## 💡 How to Use Sharded Specs\n\n`;
|
|
82
|
-
index += `### In Planning Phases (1-3)\n`;
|
|
83
|
-
index += `Load **all sections** to get complete context:\n`;
|
|
84
|
-
index += `\`\`\`bash\n`;
|
|
85
|
-
index += `# Read index.md + all section files\n`;
|
|
86
|
-
index += `\`\`\`\n\n`;
|
|
87
|
-
|
|
88
|
-
index += `### In Implementation Phase (4)\n`;
|
|
89
|
-
index += `Load **only the relevant section** for your current story:\n`;
|
|
90
|
-
index += `\`\`\`bash\n`;
|
|
91
|
-
index += `# Example: Working on entity design story\n`;
|
|
92
|
-
index += `# Read: spec/index.md + spec/entity-design.md (not the other 10 sections!)\n`;
|
|
93
|
-
index += `\`\`\`\n\n`;
|
|
94
|
-
|
|
95
|
-
index += `**Token Savings:** For a 10-section spec (30k tokens), selective loading = **90% savings**\n\n`;
|
|
96
|
-
index += `---\n\n`;
|
|
97
|
-
index += `*Generated by MORPH-SPEC Framework - Document Sharding*\n`;
|
|
98
|
-
index += `*Inspired by BMAD Method: 90% token reduction for large specs*\n`;
|
|
99
|
-
|
|
100
|
-
return index;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
function toTitleCase(str) {
|
|
104
|
-
return str
|
|
105
|
-
.split('-')
|
|
106
|
-
.map(word => word.charAt(0).toUpperCase() + word.slice(1))
|
|
107
|
-
.join(' ');
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
function estimateTokens(text) {
|
|
111
|
-
// Rough estimate: 1 token ≈ 4 characters
|
|
112
|
-
return Math.ceil(text.length / 4);
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
// ============================================================================
|
|
116
|
-
// Command Function
|
|
117
|
-
// ============================================================================
|
|
118
|
-
|
|
119
|
-
export async function shardSpecCommand(feature, options) {
|
|
120
|
-
logger.header('MORPH-SPEC Document Sharding');
|
|
121
|
-
logger.dim(`Feature: ${feature}`);
|
|
122
|
-
logger.blank();
|
|
123
|
-
|
|
124
|
-
const spinner = ora('Analyzing spec.md...').start();
|
|
125
|
-
|
|
126
|
-
try {
|
|
127
|
-
// Find spec.md
|
|
128
|
-
const specPath = path.join(process.cwd(), `.morph/project/outputs/${feature}/spec.md`);
|
|
129
|
-
if (!fs.existsSync(specPath)) {
|
|
130
|
-
throw new Error(`Spec not found: ${specPath}`);
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
// Read spec content
|
|
134
|
-
const specContent = fs.readFileSync(specPath, 'utf-8');
|
|
135
|
-
const totalTokens = estimateTokens(specContent);
|
|
136
|
-
|
|
137
|
-
spinner.info(`Original spec.md: ~${totalTokens.toLocaleString()} tokens`);
|
|
138
|
-
logger.blank();
|
|
139
|
-
|
|
140
|
-
// Parse into sections
|
|
141
|
-
const sections = parseSpec(specContent);
|
|
142
|
-
|
|
143
|
-
if (sections.length < 3) {
|
|
144
|
-
spinner.warn(`Spec has only ${sections.length} sections - sharding not recommended`);
|
|
145
|
-
logger.dim(' Sharding is most beneficial for specs with 5+ sections');
|
|
146
|
-
return;
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
spinner.succeed(`Detected ${sections.length} sections`);
|
|
150
|
-
logger.blank();
|
|
151
|
-
|
|
152
|
-
// Generate index
|
|
153
|
-
const indexContent = generateIndex(sections, feature);
|
|
154
|
-
|
|
155
|
-
// Calculate savings
|
|
156
|
-
const avgShardTokens = sections.reduce((sum, s) => sum + estimateTokens(s.content), 0) / sections.length;
|
|
157
|
-
const savingsPercent = Math.round(((totalTokens - avgShardTokens) / totalTokens) * 100);
|
|
158
|
-
|
|
159
|
-
logger.header('Token Savings (selective load):');
|
|
160
|
-
logger.info(` ${chalk.green(`~${savingsPercent}%`)} reduction`);
|
|
161
|
-
logger.dim(` - Full load: ~${totalTokens.toLocaleString()} tokens`);
|
|
162
|
-
logger.dim(` - Selective load: ~${Math.round(avgShardTokens).toLocaleString()} tokens (index + 1 shard)`);
|
|
163
|
-
logger.blank();
|
|
164
|
-
|
|
165
|
-
if (options.verbose) {
|
|
166
|
-
logger.header('Shard Details:');
|
|
167
|
-
logger.blank();
|
|
168
|
-
sections.forEach((section, i) => {
|
|
169
|
-
const tokens = estimateTokens(section.content);
|
|
170
|
-
logger.dim(` ${i + 1}. ${section.title}`);
|
|
171
|
-
logger.dim(` File: ${section.slug}.md`);
|
|
172
|
-
logger.dim(` Tokens: ~${tokens.toLocaleString()}`);
|
|
173
|
-
logger.blank();
|
|
174
|
-
});
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
// Output
|
|
178
|
-
const outputDir = path.join(process.cwd(), `.morph/project/outputs/${feature}/spec`);
|
|
179
|
-
|
|
180
|
-
if (options.dryRun) {
|
|
181
|
-
logger.header('DRY RUN - Would create:');
|
|
182
|
-
logger.dim(` ${outputDir}/index.md`);
|
|
183
|
-
sections.forEach(s => logger.dim(` ${outputDir}/${s.slug}.md`));
|
|
184
|
-
logger.blank();
|
|
185
|
-
logger.success('Run without --dry-run to create files');
|
|
186
|
-
} else {
|
|
187
|
-
const createSpinner = ora('Creating sharded spec files...').start();
|
|
188
|
-
|
|
189
|
-
// Create directory
|
|
190
|
-
await ensureDir(outputDir);
|
|
191
|
-
|
|
192
|
-
// Write index
|
|
193
|
-
await writeFile(path.join(outputDir, 'index.md'), indexContent);
|
|
194
|
-
createSpinner.text = 'Created index.md';
|
|
195
|
-
|
|
196
|
-
// Write shards
|
|
197
|
-
for (const section of sections) {
|
|
198
|
-
const shardPath = path.join(outputDir, `${section.slug}.md`);
|
|
199
|
-
await writeFile(shardPath, section.content);
|
|
200
|
-
createSpinner.text = `Created ${section.slug}.md`;
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
createSpinner.succeed('Sharded spec created!');
|
|
204
|
-
logger.blank();
|
|
205
|
-
|
|
206
|
-
// Archive original spec.md
|
|
207
|
-
const archivePath = specPath.replace('.md', '.original.md');
|
|
208
|
-
fs.renameSync(specPath, archivePath);
|
|
209
|
-
logger.dim(' Archived original: spec.original.md');
|
|
210
|
-
logger.blank();
|
|
211
|
-
|
|
212
|
-
logger.header('Next steps:');
|
|
213
|
-
logger.dim(` 1. Review sharded spec in .morph/project/outputs/${feature}/spec/`);
|
|
214
|
-
logger.dim(` 2. Create stories: morph-spec story create ${feature} SR-001`);
|
|
215
|
-
logger.dim(' 3. Stories will auto-load only relevant shards (90% token savings)');
|
|
216
|
-
logger.blank();
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
} catch (error) {
|
|
220
|
-
spinner.fail('Sharding failed');
|
|
221
|
-
logger.error(error.message);
|
|
222
|
-
process.exit(1);
|
|
223
|
-
}
|
|
224
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* MORPH-SPEC Document Sharding
|
|
3
|
+
* Splits large spec.md files into manageable shards (BMAD-inspired)
|
|
4
|
+
* Achieves 90% token savings by loading only relevant sections
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import fs from 'fs';
|
|
8
|
+
import path from 'path';
|
|
9
|
+
import ora from 'ora';
|
|
10
|
+
import chalk from 'chalk';
|
|
11
|
+
import { logger } from '../utils/logger.js';
|
|
12
|
+
import { ensureDir, writeFile } from '../utils/file-copier.js';
|
|
13
|
+
|
|
14
|
+
// ============================================================================
|
|
15
|
+
// Helper Functions
|
|
16
|
+
// ============================================================================
|
|
17
|
+
|
|
18
|
+
function parseSpec(specContent) {
|
|
19
|
+
const sections = [];
|
|
20
|
+
const lines = specContent.split('\n');
|
|
21
|
+
|
|
22
|
+
let currentSection = null;
|
|
23
|
+
let currentContent = [];
|
|
24
|
+
|
|
25
|
+
for (const line of lines) {
|
|
26
|
+
// Detect level 2 heading (## Heading)
|
|
27
|
+
if (line.match(/^## /)) {
|
|
28
|
+
// Save previous section
|
|
29
|
+
if (currentSection) {
|
|
30
|
+
sections.push({
|
|
31
|
+
title: currentSection,
|
|
32
|
+
slug: toSlug(currentSection),
|
|
33
|
+
content: currentContent.join('\n').trim(),
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Start new section
|
|
38
|
+
currentSection = line.replace(/^## /, '').trim();
|
|
39
|
+
currentContent = [line]; // Include heading in content
|
|
40
|
+
} else {
|
|
41
|
+
currentContent.push(line);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Save last section
|
|
46
|
+
if (currentSection) {
|
|
47
|
+
sections.push({
|
|
48
|
+
title: currentSection,
|
|
49
|
+
slug: toSlug(currentSection),
|
|
50
|
+
content: currentContent.join('\n').trim(),
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return sections;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function toSlug(title) {
|
|
58
|
+
return title
|
|
59
|
+
.toLowerCase()
|
|
60
|
+
.replace(/[^a-z0-9]+/g, '-')
|
|
61
|
+
.replace(/^-|-$/g, '');
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function generateIndex(sections, featureName) {
|
|
65
|
+
let index = `# ${toTitleCase(featureName)} - Technical Specification\n\n`;
|
|
66
|
+
index += `> **Sharded Spec:** This spec has been split into sections for optimal token usage\n`;
|
|
67
|
+
index += `> **BMAD Pattern:** Load only the section you need during implementation\n\n`;
|
|
68
|
+
index += `---\n\n`;
|
|
69
|
+
index += `## 📋 Table of Contents\n\n`;
|
|
70
|
+
|
|
71
|
+
sections.forEach((section, i) => {
|
|
72
|
+
index += `${i + 1}. **[${section.title}](${section.slug}.md)**\n`;
|
|
73
|
+
|
|
74
|
+
// Add first 100 chars as description
|
|
75
|
+
const firstLine = section.content.split('\n').find(l => l.trim() && !l.startsWith('#'));
|
|
76
|
+
const description = firstLine ? firstLine.substring(0, 100) + '...' : 'See section for details';
|
|
77
|
+
index += ` > ${description}\n\n`;
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
index += `---\n\n`;
|
|
81
|
+
index += `## 💡 How to Use Sharded Specs\n\n`;
|
|
82
|
+
index += `### In Planning Phases (1-3)\n`;
|
|
83
|
+
index += `Load **all sections** to get complete context:\n`;
|
|
84
|
+
index += `\`\`\`bash\n`;
|
|
85
|
+
index += `# Read index.md + all section files\n`;
|
|
86
|
+
index += `\`\`\`\n\n`;
|
|
87
|
+
|
|
88
|
+
index += `### In Implementation Phase (4)\n`;
|
|
89
|
+
index += `Load **only the relevant section** for your current story:\n`;
|
|
90
|
+
index += `\`\`\`bash\n`;
|
|
91
|
+
index += `# Example: Working on entity design story\n`;
|
|
92
|
+
index += `# Read: spec/index.md + spec/entity-design.md (not the other 10 sections!)\n`;
|
|
93
|
+
index += `\`\`\`\n\n`;
|
|
94
|
+
|
|
95
|
+
index += `**Token Savings:** For a 10-section spec (30k tokens), selective loading = **90% savings**\n\n`;
|
|
96
|
+
index += `---\n\n`;
|
|
97
|
+
index += `*Generated by MORPH-SPEC Framework - Document Sharding*\n`;
|
|
98
|
+
index += `*Inspired by BMAD Method: 90% token reduction for large specs*\n`;
|
|
99
|
+
|
|
100
|
+
return index;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function toTitleCase(str) {
|
|
104
|
+
return str
|
|
105
|
+
.split('-')
|
|
106
|
+
.map(word => word.charAt(0).toUpperCase() + word.slice(1))
|
|
107
|
+
.join(' ');
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function estimateTokens(text) {
|
|
111
|
+
// Rough estimate: 1 token ≈ 4 characters
|
|
112
|
+
return Math.ceil(text.length / 4);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// ============================================================================
|
|
116
|
+
// Command Function
|
|
117
|
+
// ============================================================================
|
|
118
|
+
|
|
119
|
+
export async function shardSpecCommand(feature, options) {
|
|
120
|
+
logger.header('MORPH-SPEC Document Sharding');
|
|
121
|
+
logger.dim(`Feature: ${feature}`);
|
|
122
|
+
logger.blank();
|
|
123
|
+
|
|
124
|
+
const spinner = ora('Analyzing spec.md...').start();
|
|
125
|
+
|
|
126
|
+
try {
|
|
127
|
+
// Find spec.md
|
|
128
|
+
const specPath = path.join(process.cwd(), `.morph/project/outputs/${feature}/spec.md`);
|
|
129
|
+
if (!fs.existsSync(specPath)) {
|
|
130
|
+
throw new Error(`Spec not found: ${specPath}`);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// Read spec content
|
|
134
|
+
const specContent = fs.readFileSync(specPath, 'utf-8');
|
|
135
|
+
const totalTokens = estimateTokens(specContent);
|
|
136
|
+
|
|
137
|
+
spinner.info(`Original spec.md: ~${totalTokens.toLocaleString()} tokens`);
|
|
138
|
+
logger.blank();
|
|
139
|
+
|
|
140
|
+
// Parse into sections
|
|
141
|
+
const sections = parseSpec(specContent);
|
|
142
|
+
|
|
143
|
+
if (sections.length < 3) {
|
|
144
|
+
spinner.warn(`Spec has only ${sections.length} sections - sharding not recommended`);
|
|
145
|
+
logger.dim(' Sharding is most beneficial for specs with 5+ sections');
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
spinner.succeed(`Detected ${sections.length} sections`);
|
|
150
|
+
logger.blank();
|
|
151
|
+
|
|
152
|
+
// Generate index
|
|
153
|
+
const indexContent = generateIndex(sections, feature);
|
|
154
|
+
|
|
155
|
+
// Calculate savings
|
|
156
|
+
const avgShardTokens = sections.reduce((sum, s) => sum + estimateTokens(s.content), 0) / sections.length;
|
|
157
|
+
const savingsPercent = Math.round(((totalTokens - avgShardTokens) / totalTokens) * 100);
|
|
158
|
+
|
|
159
|
+
logger.header('Token Savings (selective load):');
|
|
160
|
+
logger.info(` ${chalk.green(`~${savingsPercent}%`)} reduction`);
|
|
161
|
+
logger.dim(` - Full load: ~${totalTokens.toLocaleString()} tokens`);
|
|
162
|
+
logger.dim(` - Selective load: ~${Math.round(avgShardTokens).toLocaleString()} tokens (index + 1 shard)`);
|
|
163
|
+
logger.blank();
|
|
164
|
+
|
|
165
|
+
if (options.verbose) {
|
|
166
|
+
logger.header('Shard Details:');
|
|
167
|
+
logger.blank();
|
|
168
|
+
sections.forEach((section, i) => {
|
|
169
|
+
const tokens = estimateTokens(section.content);
|
|
170
|
+
logger.dim(` ${i + 1}. ${section.title}`);
|
|
171
|
+
logger.dim(` File: ${section.slug}.md`);
|
|
172
|
+
logger.dim(` Tokens: ~${tokens.toLocaleString()}`);
|
|
173
|
+
logger.blank();
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// Output
|
|
178
|
+
const outputDir = path.join(process.cwd(), `.morph/project/outputs/${feature}/spec`);
|
|
179
|
+
|
|
180
|
+
if (options.dryRun) {
|
|
181
|
+
logger.header('DRY RUN - Would create:');
|
|
182
|
+
logger.dim(` ${outputDir}/index.md`);
|
|
183
|
+
sections.forEach(s => logger.dim(` ${outputDir}/${s.slug}.md`));
|
|
184
|
+
logger.blank();
|
|
185
|
+
logger.success('Run without --dry-run to create files');
|
|
186
|
+
} else {
|
|
187
|
+
const createSpinner = ora('Creating sharded spec files...').start();
|
|
188
|
+
|
|
189
|
+
// Create directory
|
|
190
|
+
await ensureDir(outputDir);
|
|
191
|
+
|
|
192
|
+
// Write index
|
|
193
|
+
await writeFile(path.join(outputDir, 'index.md'), indexContent);
|
|
194
|
+
createSpinner.text = 'Created index.md';
|
|
195
|
+
|
|
196
|
+
// Write shards
|
|
197
|
+
for (const section of sections) {
|
|
198
|
+
const shardPath = path.join(outputDir, `${section.slug}.md`);
|
|
199
|
+
await writeFile(shardPath, section.content);
|
|
200
|
+
createSpinner.text = `Created ${section.slug}.md`;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
createSpinner.succeed('Sharded spec created!');
|
|
204
|
+
logger.blank();
|
|
205
|
+
|
|
206
|
+
// Archive original spec.md
|
|
207
|
+
const archivePath = specPath.replace('.md', '.original.md');
|
|
208
|
+
fs.renameSync(specPath, archivePath);
|
|
209
|
+
logger.dim(' Archived original: spec.original.md');
|
|
210
|
+
logger.blank();
|
|
211
|
+
|
|
212
|
+
logger.header('Next steps:');
|
|
213
|
+
logger.dim(` 1. Review sharded spec in .morph/project/outputs/${feature}/spec/`);
|
|
214
|
+
logger.dim(` 2. Create stories: morph-spec story create ${feature} SR-001`);
|
|
215
|
+
logger.dim(' 3. Stories will auto-load only relevant shards (90% token savings)');
|
|
216
|
+
logger.blank();
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
} catch (error) {
|
|
220
|
+
spinner.fail('Sharding failed');
|
|
221
|
+
logger.error(error.message);
|
|
222
|
+
process.exit(1);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
import { getFeature } from '../lib/state-manager.js';
|
|
4
|
+
import { orchestrateTeam } from '../lib/team-orchestrator.js';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Spawn Team Command - Generate agent team configurations
|
|
8
|
+
*
|
|
9
|
+
* Reads active agents from feature state and generates ready-to-use
|
|
10
|
+
* Task tool configurations for spawning agent teams.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
const program = new Command();
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Spawn team action function
|
|
17
|
+
*/
|
|
18
|
+
export async function spawnTeamCommand(featureName, options = {}) {
|
|
19
|
+
try {
|
|
20
|
+
// Get feature state
|
|
21
|
+
const feature = getFeature(featureName);
|
|
22
|
+
if (!feature) {
|
|
23
|
+
console.error(chalk.red(`\n❌ Feature not found: ${featureName}\n`));
|
|
24
|
+
process.exit(1);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
if (!feature.activeAgents || feature.activeAgents.length === 0) {
|
|
28
|
+
console.error(chalk.yellow(`\n⚠️ No active agents found for feature: ${featureName}`));
|
|
29
|
+
console.log(chalk.gray('Run "morph-spec detect-agents" first to identify agents.\n'));
|
|
30
|
+
process.exit(1);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Determine if multi-domain
|
|
34
|
+
const domains = new Set();
|
|
35
|
+
feature.activeAgents.forEach(agentId => {
|
|
36
|
+
if (agentId.includes('dotnet') || agentId.includes('ef') || agentId.includes('api')) {
|
|
37
|
+
domains.add('backend');
|
|
38
|
+
}
|
|
39
|
+
if (agentId.includes('blazor') || agentId.includes('nextjs') || agentId.includes('ui')) {
|
|
40
|
+
domains.add('frontend');
|
|
41
|
+
}
|
|
42
|
+
if (agentId.includes('azure') || agentId.includes('bicep') || agentId.includes('container')) {
|
|
43
|
+
domains.add('infrastructure');
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
const multiDomain = domains.size > 1;
|
|
48
|
+
|
|
49
|
+
// Orchestrate team
|
|
50
|
+
const teamConfig = orchestrateTeam({
|
|
51
|
+
activeAgents: feature.activeAgents,
|
|
52
|
+
complexity: options.complexity,
|
|
53
|
+
estimatedFiles: parseInt(options.estimatedFiles, 10),
|
|
54
|
+
multiDomain
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
if (options.json) {
|
|
58
|
+
// Output as JSON for programmatic use
|
|
59
|
+
console.log(JSON.stringify(teamConfig, null, 2));
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// Pretty output for human reading
|
|
64
|
+
console.log(chalk.bold(`\n🤖 Agent Team Configuration for: ${featureName}`));
|
|
65
|
+
console.log('━'.repeat(60));
|
|
66
|
+
|
|
67
|
+
console.log(chalk.cyan(`\nShould Spawn Agents: ${teamConfig.useAgentTeams ? chalk.green('YES') : chalk.yellow('NO')}`));
|
|
68
|
+
console.log(chalk.gray(`Reason: ${teamConfig.useAgentTeams ? 'Meets spawn threshold' : 'Below threshold - implement directly'}`));
|
|
69
|
+
|
|
70
|
+
if (!teamConfig.useAgentTeams) {
|
|
71
|
+
console.log(chalk.yellow('\n⚠️ Team spawning not recommended for this feature.'));
|
|
72
|
+
console.log(chalk.gray('Implement directly in main session.\n'));
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
console.log(chalk.cyan(`\nDisplay Mode: ${teamConfig.displayMode}`));
|
|
77
|
+
console.log(chalk.cyan(`Total Teammates: ${teamConfig.teamHierarchy.totalTeammates}`));
|
|
78
|
+
|
|
79
|
+
// Show team hierarchy
|
|
80
|
+
console.log(chalk.bold('\nTeam Hierarchy:'));
|
|
81
|
+
console.log(chalk.green(` Team Lead: ${teamConfig.teamHierarchy.teamLead}`));
|
|
82
|
+
|
|
83
|
+
if (teamConfig.teamHierarchy.squads && teamConfig.teamHierarchy.squads.length > 0) {
|
|
84
|
+
console.log(chalk.cyan('\n Squad Leaders:'));
|
|
85
|
+
teamConfig.teamHierarchy.squads.forEach(squad => {
|
|
86
|
+
console.log(chalk.cyan(` • ${squad}`));
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
if (teamConfig.teamHierarchy.validators && teamConfig.teamHierarchy.validators.length > 0) {
|
|
91
|
+
console.log(chalk.gray('\n Validators (run in hooks):'));
|
|
92
|
+
teamConfig.teamHierarchy.validators.forEach(validator => {
|
|
93
|
+
console.log(chalk.gray(` • ${validator}`));
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Show Task tool usage
|
|
98
|
+
console.log(chalk.bold('\n📝 Task Tool Usage:'));
|
|
99
|
+
console.log(chalk.gray('\nUse the following pattern to spawn the team:\n'));
|
|
100
|
+
|
|
101
|
+
console.log(chalk.cyan('```typescript'));
|
|
102
|
+
console.log(chalk.white(`{
|
|
103
|
+
subagent_type: "general-purpose",
|
|
104
|
+
description: "Implement ${featureName}",
|
|
105
|
+
prompt: \`You are the Team Lead (${teamConfig.teamHierarchy.teamLead})...
|
|
106
|
+
|
|
107
|
+
Your Mission: Implement ${featureName}
|
|
108
|
+
|
|
109
|
+
Your Domain Leaders:
|
|
110
|
+
${teamConfig.teammates
|
|
111
|
+
.filter(t => t.tier === 2)
|
|
112
|
+
.map(t => `- ${t.id}: ${t.role}`)
|
|
113
|
+
.join('\n')}
|
|
114
|
+
|
|
115
|
+
Your Specialists:
|
|
116
|
+
${teamConfig.teammates
|
|
117
|
+
.filter(t => t.tier === 3)
|
|
118
|
+
.map(t => `- ${t.id}: ${t.role}`)
|
|
119
|
+
.join('\n')}
|
|
120
|
+
|
|
121
|
+
Standards to follow: [coding.md, architecture.md]
|
|
122
|
+
|
|
123
|
+
Deliverables: [list specific outputs]
|
|
124
|
+
\`
|
|
125
|
+
}`));
|
|
126
|
+
console.log(chalk.cyan('```\n'));
|
|
127
|
+
|
|
128
|
+
// Show individual teammates
|
|
129
|
+
console.log(chalk.bold('Individual Teammates:'));
|
|
130
|
+
teamConfig.teammates.forEach(teammate => {
|
|
131
|
+
console.log(chalk.cyan(`\n ${teammate.icon} ${teammate.id} (Tier ${teammate.tier})`));
|
|
132
|
+
console.log(chalk.gray(` Role: ${teammate.role}`));
|
|
133
|
+
|
|
134
|
+
if (teammate.spawnPrompt && teammate.spawnPrompt.length < 200) {
|
|
135
|
+
console.log(chalk.gray(` Prompt: ${teammate.spawnPrompt.substring(0, 100)}...`));
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
console.log('\n' + '━'.repeat(60));
|
|
140
|
+
console.log(chalk.green('\n✅ Team configuration generated successfully\n'));
|
|
141
|
+
|
|
142
|
+
} catch (error) {
|
|
143
|
+
console.error(chalk.red(`\n❌ Error generating team configuration: ${error.message}\n`));
|
|
144
|
+
if (error.stack) {
|
|
145
|
+
console.error(chalk.gray(error.stack));
|
|
146
|
+
}
|
|
147
|
+
process.exit(1);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Commander program command
|
|
153
|
+
*/
|
|
154
|
+
program
|
|
155
|
+
.name('spawn-team')
|
|
156
|
+
.description('Generate agent team configuration for Task tool spawning')
|
|
157
|
+
.argument('<feature>', 'Feature name')
|
|
158
|
+
.option('--json', 'Output as JSON')
|
|
159
|
+
.option('--complexity <level>', 'Override complexity level (low/medium/high/critical)', 'high')
|
|
160
|
+
.option('--estimated-files <count>', 'Override estimated file count', '20')
|
|
161
|
+
.action(spawnTeamCommand);
|
|
162
|
+
|
|
163
|
+
// Only parse if run directly (not imported as module)
|
|
164
|
+
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
165
|
+
if (process.argv.length > 2) {
|
|
166
|
+
program.parse(process.argv);
|
|
167
|
+
} else {
|
|
168
|
+
program.help();
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
export default program;
|