@polymorphism-tech/morph-spec 3.2.0 → 4.3.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/README.md +1 -14
- package/bin/detect-agents.js +1 -1
- package/bin/morph-spec.js +403 -40
- package/bin/validate.js +5 -5
- package/docs/getting-started.md +0 -5
- package/docs/next-generation/AGENTS.md +521 -0
- package/docs/next-generation/ANALYSIS.md +555 -0
- package/docs/next-generation/ARCHITECTURE.md +436 -0
- package/docs/next-generation/CONTEXT-OPTIMIZATION.md +267 -0
- package/docs/next-generation/EXECUTION-FLOW.md +274 -0
- package/docs/next-generation/FEATURES.md +688 -0
- package/docs/next-generation/META-PROMPTS.md +235 -0
- package/docs/next-generation/MIGRATION-GUIDE.md +253 -0
- package/docs/next-generation/README.md +231 -0
- package/docs/next-generation/ROADMAP.md +801 -0
- package/docs/next-generation/THREAD-MANAGEMENT.md +240 -0
- package/docs/validation-checklist.md +0 -1
- package/package.json +5 -5
- package/src/commands/agents/agents-fuse.js +96 -0
- package/src/commands/agents/index.js +4 -0
- package/src/commands/agents/micro-agent.js +112 -0
- package/src/commands/{spawn-team.js → agents/spawn-team.js} +237 -172
- package/src/commands/agents/squad-template.js +146 -0
- package/src/commands/analytics/analytics.js +176 -0
- package/src/commands/context/context-prime.js +63 -0
- package/src/commands/context/core-four.js +54 -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} +4 -4
- package/src/commands/generation/index.js +5 -0
- package/src/commands/index.js +16 -0
- package/src/commands/{capture-pattern.js → learning/capture-pattern.js} +121 -121
- package/src/commands/learning/index.js +5 -0
- package/src/commands/mcp/mcp.js +102 -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} +221 -4
- package/src/commands/project/index.js +10 -0
- package/src/commands/{init.js → project/init.js} +305 -295
- package/src/commands/{sync.js → project/sync.js} +167 -167
- package/src/commands/{update.js → project/update.js} +240 -240
- package/src/commands/{advance-phase.js → state/advance-phase.js} +101 -25
- package/src/commands/{approve.js → state/approve.js} +221 -221
- 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 +174 -0
- package/src/commands/templates/template-show.js +131 -0
- package/src/commands/templates/template-validate.js +91 -0
- package/src/commands/threads/thread-template.js +103 -0
- package/src/commands/threads/threads.js +261 -0
- package/src/commands/trust/trust.js +205 -0
- package/src/commands/utils/index.js +7 -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/{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/{orchestrator.js → core/orchestrator.js} +8 -8
- 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/{lib → core/state}/phase-state-machine.js +214 -214
- package/src/{lib → core/state}/state-manager.js +588 -534
- package/src/core/templates/index.js +9 -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 +452 -0
- package/src/lib/agents/micro-agent-factory.js +161 -0
- package/src/lib/{complexity-analyzer.js → analysis/complexity-analyzer.js} +441 -441
- package/src/lib/analysis/index.js +7 -0
- package/src/lib/analytics/analytics-engine.js +345 -0
- package/src/lib/{checkpoint-hooks.js → checkpoints/checkpoint-hooks.js} +35 -0
- package/src/lib/checkpoints/index.js +7 -0
- package/src/lib/context/context-bundler.js +240 -0
- package/src/lib/context/context-optimizer.js +212 -0
- package/src/lib/context/context-tracker.js +273 -0
- package/src/lib/context/core-four-tracker.js +201 -0
- package/src/lib/context/mcp-optimizer.js +200 -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/execution/fusion-executor.js +304 -0
- package/src/lib/execution/parallel-executor.js +270 -0
- package/src/lib/{context-generator.js → generators/context-generator.js} +526 -516
- package/src/lib/generators/index.js +10 -0
- package/src/lib/{metadata-extractor.js → generators/metadata-extractor.js} +387 -380
- package/src/lib/{recap-generator.js → generators/recap-generator.js} +205 -205
- package/src/lib/hooks/hook-executor.js +169 -0
- package/src/lib/hooks/stop-hook-executor.js +286 -0
- package/src/lib/hops/hop-composer.js +221 -0
- 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/threads/thread-coordinator.js +238 -0
- package/src/lib/threads/thread-manager.js +317 -0
- package/src/lib/tracking/artifact-trail.js +202 -0
- 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/trust/trust-manager.js +269 -0
- package/src/lib/validators/{architecture-validator.js → architecture/architecture-validator.js} +8 -8
- package/src/lib/validators/architecture/index.js +7 -0
- 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-validator.js → content/content-validator.js} +351 -351
- package/src/lib/validators/content/index.js +7 -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/packages/index.js +7 -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/{validation-runner.js → validators/validation-runner.js} +286 -284
- package/src/ui/wizard-questions.js +0 -2
- 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/stacks/blazor-azure/.morph/config/agents.json +948 -764
- package/stacks/blazor-azure/.morph/hooks/{pre-commit-tests.sh → pre-commit/tests-csharp.sh} +3 -2
- 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/.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/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/CLAUDE.md +0 -648
- package/bin/render-template.js +0 -349
- 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/docs/llm-interaction-config.md +0 -735
- 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/commands/migrate-state.js +0 -158
- package/src/commands/upgrade.js +0 -346
- 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/src/llm/schema-validator.js +0 -121
- package/src/sanitizer/.gitkeep +0 -0
- package/src/scanner/.gitkeep +0 -0
- package/src/types/index.js +0 -477
- package/src/ui/.gitkeep +0 -0
- package/src/writer/.gitkeep +0 -0
- 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/commands/morph-apply.md +0 -221
- package/stacks/blazor-azure/.claude/commands/morph-archive.md +0 -79
- package/stacks/blazor-azure/.claude/commands/morph-deploy.md +0 -529
- package/stacks/blazor-azure/.claude/commands/morph-infra.md +0 -209
- package/stacks/blazor-azure/.claude/commands/morph-preflight.md +0 -227
- package/stacks/blazor-azure/.claude/commands/morph-proposal.md +0 -122
- package/stacks/blazor-azure/.claude/commands/morph-status.md +0 -86
- package/stacks/blazor-azure/.claude/commands/morph-troubleshoot.md +0 -122
- package/stacks/blazor-azure/.claude/settings.local.json +0 -15
- package/stacks/blazor-azure/.claude/skills/level-0-meta/README.md +0 -7
- package/stacks/blazor-azure/.claude/skills/level-0-meta/code-review.md +0 -226
- package/stacks/blazor-azure/.claude/skills/level-0-meta/morph-checklist.md +0 -117
- package/stacks/blazor-azure/.claude/skills/level-0-meta/simulation-checklist.md +0 -77
- package/stacks/blazor-azure/.claude/skills/level-1-workflows/README.md +0 -7
- package/stacks/blazor-azure/.claude/skills/level-1-workflows/morph-replicate.md +0 -213
- package/stacks/blazor-azure/.claude/skills/level-1-workflows/phase-clarify.md +0 -131
- package/stacks/blazor-azure/.claude/skills/level-1-workflows/phase-design.md +0 -213
- package/stacks/blazor-azure/.claude/skills/level-1-workflows/phase-setup.md +0 -106
- package/stacks/blazor-azure/.claude/skills/level-1-workflows/phase-tasks.md +0 -164
- package/stacks/blazor-azure/.claude/skills/level-1-workflows/phase-uiux.md +0 -169
- package/stacks/blazor-azure/.claude/skills/level-2-domains/README.md +0 -14
- package/stacks/blazor-azure/.claude/skills/level-2-domains/ai-agents/ai-system-architect.md +0 -192
- package/stacks/blazor-azure/.claude/skills/level-2-domains/architecture/po-pm-advisor.md +0 -197
- package/stacks/blazor-azure/.claude/skills/level-2-domains/architecture/prompt-engineer.md +0 -189
- package/stacks/blazor-azure/.claude/skills/level-2-domains/architecture/seo-growth-hacker.md +0 -320
- package/stacks/blazor-azure/.claude/skills/level-2-domains/architecture/standards-architect.md +0 -156
- package/stacks/blazor-azure/.claude/skills/level-2-domains/backend/dotnet-senior.md +0 -287
- package/stacks/blazor-azure/.claude/skills/level-2-domains/backend/ef-modeler.md +0 -113
- package/stacks/blazor-azure/.claude/skills/level-2-domains/backend/hangfire-orchestrator.md +0 -126
- package/stacks/blazor-azure/.claude/skills/level-2-domains/backend/ms-agent-expert.md +0 -109
- package/stacks/blazor-azure/.claude/skills/level-2-domains/frontend/blazor-builder.md +0 -210
- package/stacks/blazor-azure/.claude/skills/level-2-domains/frontend/nextjs-expert.md +0 -154
- package/stacks/blazor-azure/.claude/skills/level-2-domains/frontend/ui-ux-designer.md +0 -191
- package/stacks/blazor-azure/.claude/skills/level-2-domains/infrastructure/azure-architect.md +0 -142
- package/stacks/blazor-azure/.claude/skills/level-2-domains/infrastructure/azure-deploy-specialist.md +0 -699
- package/stacks/blazor-azure/.claude/skills/level-2-domains/infrastructure/bicep-architect.md +0 -126
- package/stacks/blazor-azure/.claude/skills/level-2-domains/infrastructure/container-specialist.md +0 -131
- package/stacks/blazor-azure/.claude/skills/level-2-domains/infrastructure/devops-engineer.md +0 -119
- package/stacks/blazor-azure/.claude/skills/level-2-domains/integrations/asaas-financial.md +0 -130
- package/stacks/blazor-azure/.claude/skills/level-2-domains/integrations/azure-identity.md +0 -142
- package/stacks/blazor-azure/.claude/skills/level-2-domains/integrations/clerk-auth.md +0 -108
- package/stacks/blazor-azure/.claude/skills/level-2-domains/integrations/resend-email.md +0 -119
- package/stacks/blazor-azure/.claude/skills/level-2-domains/quality/code-analyzer.md +0 -235
- package/stacks/blazor-azure/.claude/skills/level-2-domains/quality/testing-specialist.md +0 -126
- package/stacks/blazor-azure/.claude/skills/level-3-technologies/README.md +0 -7
- package/stacks/blazor-azure/.claude/skills/level-4-patterns/README.md +0 -7
- package/stacks/blazor-azure/.morph/archive/.gitkeep +0 -25
- 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/features/.gitkeep +0 -25
- 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/schemas/agent.schema.json +0 -296
- package/stacks/blazor-azure/.morph/schemas/tasks.schema.json +0 -220
- package/stacks/blazor-azure/.morph/specs/.gitkeep +0 -20
- 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/blazor-azure/.morph/test-infra/example.bicep +0 -59
- package/stacks/nextjs-supabase/.claude/skills/level-2-domains/backend/dotnet-supabase.md +0 -244
- package/stacks/nextjs-supabase/.claude/skills/level-2-domains/frontend/nextjs-supabase.md +0 -335
- package/stacks/nextjs-supabase/.claude/skills/level-2-domains/infrastructure/easypanel-deployer.md +0 -189
- package/stacks/nextjs-supabase/.claude/skills/level-2-domains/integrations/supabase-expert.md +0 -170
- 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/commands/{search-patterns.js → learning/search-patterns.js} +0 -0
- /package/src/{lib → core/templates}/template-data-sources.js +0 -0
- /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/validators/{package-validator.js → packages/package-validator.js} +0 -0
- /package/src/lib/validators/{ui-contrast-validator.js → ui/ui-contrast-validator.js} +0 -0
- /package/{src/generator → stacks/blazor-azure/.morph/templates}/.gitkeep +0 -0
- /package/{src/llm → stacks/nextjs-supabase/.morph/templates}/.gitkeep +0 -0
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Artifact Trail — Debugging trail system
|
|
3
|
+
*
|
|
4
|
+
* Creates checkpoint artifact directories and saves:
|
|
5
|
+
* - Intermediate files (spec drafts, contract drafts)
|
|
6
|
+
* - Agent reasoning logs
|
|
7
|
+
* - Validator output logs
|
|
8
|
+
* - Failure artifacts on checkpoint failure
|
|
9
|
+
*
|
|
10
|
+
* Structure:
|
|
11
|
+
* .morph/features/{feature}/artifacts/
|
|
12
|
+
* checkpoint-{n}/
|
|
13
|
+
* spec-draft.md
|
|
14
|
+
* contracts-draft.cs
|
|
15
|
+
* agent-reasoning.json
|
|
16
|
+
* validator-output.json
|
|
17
|
+
* checkpoint-{n}/failures/
|
|
18
|
+
* failure-detail.json
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
import { readFileSync, writeFileSync, existsSync, mkdirSync, readdirSync } from 'fs';
|
|
22
|
+
import { join } from 'path';
|
|
23
|
+
|
|
24
|
+
const BASE_DIR = join(process.cwd(), '.morph/features');
|
|
25
|
+
|
|
26
|
+
// ============================================================================
|
|
27
|
+
// Path Helpers
|
|
28
|
+
// ============================================================================
|
|
29
|
+
|
|
30
|
+
function artifactsDir(feature) {
|
|
31
|
+
return join(BASE_DIR, feature, 'artifacts');
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function checkpointDir(feature, checkpointNum) {
|
|
35
|
+
return join(artifactsDir(feature), `checkpoint-${checkpointNum}`);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function failuresDir(feature, checkpointNum) {
|
|
39
|
+
return join(checkpointDir(feature, checkpointNum), 'failures');
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function ensureDir(dir) {
|
|
43
|
+
if (!existsSync(dir)) {
|
|
44
|
+
mkdirSync(dir, { recursive: true });
|
|
45
|
+
}
|
|
46
|
+
return dir;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// ============================================================================
|
|
50
|
+
// Checkpoint Artifacts
|
|
51
|
+
// ============================================================================
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Initialize a checkpoint artifact directory
|
|
55
|
+
* @param {string} feature - Feature name
|
|
56
|
+
* @param {number} checkpointNum - Checkpoint number
|
|
57
|
+
* @returns {string} Path to checkpoint directory
|
|
58
|
+
*/
|
|
59
|
+
export function initCheckpointArtifacts(feature, checkpointNum) {
|
|
60
|
+
const dir = checkpointDir(feature, checkpointNum);
|
|
61
|
+
ensureDir(dir);
|
|
62
|
+
|
|
63
|
+
const manifest = {
|
|
64
|
+
feature,
|
|
65
|
+
checkpointNum,
|
|
66
|
+
createdAt: new Date().toISOString(),
|
|
67
|
+
files: []
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
writeFileSync(join(dir, 'manifest.json'), JSON.stringify(manifest, null, 2), 'utf8');
|
|
71
|
+
return dir;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Save an intermediate artifact file to a checkpoint directory
|
|
76
|
+
* @param {string} feature - Feature name
|
|
77
|
+
* @param {number} checkpointNum - Checkpoint number
|
|
78
|
+
* @param {string} filename - File name (e.g., 'spec-draft.md')
|
|
79
|
+
* @param {string} content - File content
|
|
80
|
+
* @returns {string} Full path to saved file
|
|
81
|
+
*/
|
|
82
|
+
export function saveArtifact(feature, checkpointNum, filename, content) {
|
|
83
|
+
const dir = ensureDir(checkpointDir(feature, checkpointNum));
|
|
84
|
+
const filePath = join(dir, filename);
|
|
85
|
+
|
|
86
|
+
writeFileSync(filePath, content, 'utf8');
|
|
87
|
+
|
|
88
|
+
// Update manifest
|
|
89
|
+
const manifestPath = join(dir, 'manifest.json');
|
|
90
|
+
if (existsSync(manifestPath)) {
|
|
91
|
+
const manifest = JSON.parse(readFileSync(manifestPath, 'utf8'));
|
|
92
|
+
if (!manifest.files.includes(filename)) {
|
|
93
|
+
manifest.files.push(filename);
|
|
94
|
+
manifest.updatedAt = new Date().toISOString();
|
|
95
|
+
writeFileSync(manifestPath, JSON.stringify(manifest, null, 2), 'utf8');
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
return filePath;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Save agent reasoning log
|
|
104
|
+
* @param {string} feature - Feature name
|
|
105
|
+
* @param {number} checkpointNum - Checkpoint number
|
|
106
|
+
* @param {Object} reasoning - Agent reasoning data
|
|
107
|
+
*/
|
|
108
|
+
export function saveAgentReasoning(feature, checkpointNum, reasoning) {
|
|
109
|
+
const entry = {
|
|
110
|
+
timestamp: new Date().toISOString(),
|
|
111
|
+
...reasoning
|
|
112
|
+
};
|
|
113
|
+
saveArtifact(feature, checkpointNum, 'agent-reasoning.json', JSON.stringify(entry, null, 2));
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Save validator output log
|
|
118
|
+
* @param {string} feature - Feature name
|
|
119
|
+
* @param {number} checkpointNum - Checkpoint number
|
|
120
|
+
* @param {Object} validatorOutput - Validator results
|
|
121
|
+
*/
|
|
122
|
+
export function saveValidatorOutput(feature, checkpointNum, validatorOutput) {
|
|
123
|
+
const entry = {
|
|
124
|
+
timestamp: new Date().toISOString(),
|
|
125
|
+
...validatorOutput
|
|
126
|
+
};
|
|
127
|
+
saveArtifact(feature, checkpointNum, 'validator-output.json', JSON.stringify(entry, null, 2));
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// ============================================================================
|
|
131
|
+
// Failure Artifacts
|
|
132
|
+
// ============================================================================
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Save failure artifacts when a checkpoint fails
|
|
136
|
+
* @param {string} feature - Feature name
|
|
137
|
+
* @param {number} checkpointNum - Checkpoint number
|
|
138
|
+
* @param {Object} failure - Failure details
|
|
139
|
+
* @param {string} failure.reason - Failure reason
|
|
140
|
+
* @param {Array} failure.errors - Array of error objects
|
|
141
|
+
* @param {number} failure.attemptNumber - Which retry attempt (1-3)
|
|
142
|
+
*/
|
|
143
|
+
export function saveFailureArtifacts(feature, checkpointNum, failure) {
|
|
144
|
+
const dir = ensureDir(failuresDir(feature, checkpointNum));
|
|
145
|
+
const filename = `failure-attempt-${failure.attemptNumber || 1}.json`;
|
|
146
|
+
|
|
147
|
+
const entry = {
|
|
148
|
+
feature,
|
|
149
|
+
checkpointNum,
|
|
150
|
+
timestamp: new Date().toISOString(),
|
|
151
|
+
...failure
|
|
152
|
+
};
|
|
153
|
+
|
|
154
|
+
writeFileSync(join(dir, filename), JSON.stringify(entry, null, 2), 'utf8');
|
|
155
|
+
return join(dir, filename);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Get all failure artifacts for a checkpoint
|
|
160
|
+
* @param {string} feature - Feature name
|
|
161
|
+
* @param {number} checkpointNum - Checkpoint number
|
|
162
|
+
* @returns {Array} Array of failure records
|
|
163
|
+
*/
|
|
164
|
+
export function getFailureArtifacts(feature, checkpointNum) {
|
|
165
|
+
const dir = failuresDir(feature, checkpointNum);
|
|
166
|
+
if (!existsSync(dir)) return [];
|
|
167
|
+
|
|
168
|
+
const files = readdirSync(dir).filter(f => f.endsWith('.json'));
|
|
169
|
+
|
|
170
|
+
return files.map(f => {
|
|
171
|
+
try {
|
|
172
|
+
return JSON.parse(readFileSync(join(dir, f), 'utf8'));
|
|
173
|
+
} catch {
|
|
174
|
+
return null;
|
|
175
|
+
}
|
|
176
|
+
}).filter(Boolean);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* List all checkpoints for a feature
|
|
181
|
+
* @param {string} feature - Feature name
|
|
182
|
+
* @returns {Array} Array of checkpoint info objects
|
|
183
|
+
*/
|
|
184
|
+
export function listCheckpointArtifacts(feature) {
|
|
185
|
+
const dir = artifactsDir(feature);
|
|
186
|
+
if (!existsSync(dir)) return [];
|
|
187
|
+
|
|
188
|
+
try {
|
|
189
|
+
return readdirSync(dir, { withFileTypes: true })
|
|
190
|
+
.filter(d => d.isDirectory() && d.name.startsWith('checkpoint-'))
|
|
191
|
+
.map(d => {
|
|
192
|
+
const checkpointPath = join(dir, d.name);
|
|
193
|
+
const manifestPath = join(checkpointPath, 'manifest.json');
|
|
194
|
+
if (existsSync(manifestPath)) {
|
|
195
|
+
return JSON.parse(readFileSync(manifestPath, 'utf8'));
|
|
196
|
+
}
|
|
197
|
+
return { name: d.name, path: checkpointPath };
|
|
198
|
+
});
|
|
199
|
+
} catch {
|
|
200
|
+
return [];
|
|
201
|
+
}
|
|
202
|
+
}
|
|
@@ -1,204 +1,204 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Troubleshoot Grep Fallback
|
|
3
|
-
* Searches markdown files for matching content when index doesn't find results
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { readFileSync, readdirSync, existsSync } from 'fs';
|
|
7
|
-
import { join, dirname, basename } from 'path';
|
|
8
|
-
import { fileURLToPath } from 'url';
|
|
9
|
-
import { resolveStandardsDir } from '
|
|
10
|
-
|
|
11
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
12
|
-
const __dirname = dirname(__filename);
|
|
13
|
-
const frameworkRoot = join(__dirname, '..', '..');
|
|
14
|
-
|
|
15
|
-
// Directories to search (stack standards resolved dynamically)
|
|
16
|
-
const SEARCH_PATHS = [
|
|
17
|
-
'framework/standards',
|
|
18
|
-
'.wiki'
|
|
19
|
-
];
|
|
20
|
-
|
|
21
|
-
function getSearchPaths(basePath) {
|
|
22
|
-
const paths = [...SEARCH_PATHS];
|
|
23
|
-
// Insert resolved stack standards path
|
|
24
|
-
const stackStandards = resolveStandardsDir(basePath || frameworkRoot);
|
|
25
|
-
const relativePath = stackStandards.replace(basePath || frameworkRoot, '').replace(/^[\\/]/, '');
|
|
26
|
-
paths.splice(1, 0, relativePath);
|
|
27
|
-
return paths;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* Get all markdown files from search paths
|
|
32
|
-
* @param {string} basePath - Base path of the project
|
|
33
|
-
* @returns {string[]} Array of file paths
|
|
34
|
-
*/
|
|
35
|
-
function getMarkdownFiles(basePath) {
|
|
36
|
-
const files = [];
|
|
37
|
-
|
|
38
|
-
for (const searchPath of getSearchPaths(basePath)) {
|
|
39
|
-
const fullPath = join(basePath, searchPath);
|
|
40
|
-
|
|
41
|
-
if (!existsSync(fullPath)) {
|
|
42
|
-
continue;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
try {
|
|
46
|
-
const entries = readdirSync(fullPath, { withFileTypes: true });
|
|
47
|
-
|
|
48
|
-
for (const entry of entries) {
|
|
49
|
-
if (entry.isFile() && entry.name.endsWith('.md')) {
|
|
50
|
-
files.push(join(fullPath, entry.name));
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
} catch (error) {
|
|
54
|
-
// Skip directories we can't read
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
return files;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
* Extract section containing the match
|
|
63
|
-
* @param {string} content - File content
|
|
64
|
-
* @param {number} matchIndex - Index of the match
|
|
65
|
-
* @returns {Object} Section object with title and content
|
|
66
|
-
*/
|
|
67
|
-
function extractSection(content, matchIndex) {
|
|
68
|
-
const lines = content.split('\n');
|
|
69
|
-
let charCount = 0;
|
|
70
|
-
let matchLineIndex = 0;
|
|
71
|
-
|
|
72
|
-
// Find the line containing the match
|
|
73
|
-
for (let i = 0; i < lines.length; i++) {
|
|
74
|
-
charCount += lines[i].length + 1; // +1 for newline
|
|
75
|
-
if (charCount > matchIndex) {
|
|
76
|
-
matchLineIndex = i;
|
|
77
|
-
break;
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
// Find the section header (## heading) above the match
|
|
82
|
-
let sectionTitle = 'Unknown Section';
|
|
83
|
-
let sectionStart = 0;
|
|
84
|
-
|
|
85
|
-
for (let i = matchLineIndex; i >= 0; i--) {
|
|
86
|
-
if (lines[i].startsWith('## ')) {
|
|
87
|
-
sectionTitle = lines[i].replace('## ', '').trim();
|
|
88
|
-
sectionStart = i;
|
|
89
|
-
break;
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
// Find the end of the section (next ## or end of file)
|
|
94
|
-
let sectionEnd = lines.length;
|
|
95
|
-
for (let i = sectionStart + 1; i < lines.length; i++) {
|
|
96
|
-
if (lines[i].startsWith('## ')) {
|
|
97
|
-
sectionEnd = i;
|
|
98
|
-
break;
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
// Extract section content (limit to ~20 lines around match)
|
|
103
|
-
const contextStart = Math.max(sectionStart, matchLineIndex - 10);
|
|
104
|
-
const contextEnd = Math.min(sectionEnd, matchLineIndex + 10);
|
|
105
|
-
const sectionContent = lines.slice(contextStart, contextEnd).join('\n');
|
|
106
|
-
|
|
107
|
-
return {
|
|
108
|
-
title: sectionTitle,
|
|
109
|
-
content: sectionContent,
|
|
110
|
-
lineNumber: matchLineIndex + 1
|
|
111
|
-
};
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
/**
|
|
115
|
-
* Search a file for keywords
|
|
116
|
-
* @param {string} filePath - Path to the file
|
|
117
|
-
* @param {string[]} keywords - Keywords to search for
|
|
118
|
-
* @returns {Object[]} Array of matches
|
|
119
|
-
*/
|
|
120
|
-
function searchFile(filePath, keywords) {
|
|
121
|
-
const matches = [];
|
|
122
|
-
|
|
123
|
-
try {
|
|
124
|
-
const content = readFileSync(filePath, 'utf-8');
|
|
125
|
-
const contentLower = content.toLowerCase();
|
|
126
|
-
|
|
127
|
-
for (const keyword of keywords) {
|
|
128
|
-
const keywordLower = keyword.toLowerCase();
|
|
129
|
-
let index = contentLower.indexOf(keywordLower);
|
|
130
|
-
|
|
131
|
-
while (index !== -1) {
|
|
132
|
-
const section = extractSection(content, index);
|
|
133
|
-
|
|
134
|
-
// Check if we already have a match for this section
|
|
135
|
-
const existingMatch = matches.find(m => m.section === section.title);
|
|
136
|
-
|
|
137
|
-
if (existingMatch) {
|
|
138
|
-
existingMatch.matchCount++;
|
|
139
|
-
existingMatch.keywords.add(keyword);
|
|
140
|
-
} else {
|
|
141
|
-
matches.push({
|
|
142
|
-
file: filePath,
|
|
143
|
-
fileName: basename(filePath),
|
|
144
|
-
section: section.title,
|
|
145
|
-
content: section.content,
|
|
146
|
-
lineNumber: section.lineNumber,
|
|
147
|
-
matchCount: 1,
|
|
148
|
-
keywords: new Set([keyword])
|
|
149
|
-
});
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
index = contentLower.indexOf(keywordLower, index + 1);
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
} catch (error) {
|
|
156
|
-
// Skip files we can't read
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
return matches;
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
/**
|
|
163
|
-
* Search all markdown files for keywords
|
|
164
|
-
* @param {string[]} keywords - Keywords to search for
|
|
165
|
-
* @param {Object} options - Search options
|
|
166
|
-
* @returns {Object[]} Array of matches sorted by relevance
|
|
167
|
-
*/
|
|
168
|
-
export function searchGrep(keywords, options = {}) {
|
|
169
|
-
// Determine base path
|
|
170
|
-
const basePath = options.basePath || join(__dirname, '../..');
|
|
171
|
-
|
|
172
|
-
const files = getMarkdownFiles(basePath);
|
|
173
|
-
let allMatches = [];
|
|
174
|
-
|
|
175
|
-
for (const file of files) {
|
|
176
|
-
const matches = searchFile(file, keywords);
|
|
177
|
-
allMatches = allMatches.concat(matches);
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
// Convert keywords Set to Array and calculate score
|
|
181
|
-
const results = allMatches.map(match => ({
|
|
182
|
-
...match,
|
|
183
|
-
keywords: Array.from(match.keywords),
|
|
184
|
-
score: match.matchCount * 5 + match.keywords.size * 3,
|
|
185
|
-
source: 'grep'
|
|
186
|
-
}));
|
|
187
|
-
|
|
188
|
-
// Sort by score (higher is better) and deduplicate
|
|
189
|
-
const seen = new Set();
|
|
190
|
-
const uniqueResults = results
|
|
191
|
-
.sort((a, b) => b.score - a.score)
|
|
192
|
-
.filter(r => {
|
|
193
|
-
const key = `${r.file}:${r.section}`;
|
|
194
|
-
if (seen.has(key)) return false;
|
|
195
|
-
seen.add(key);
|
|
196
|
-
return true;
|
|
197
|
-
});
|
|
198
|
-
|
|
199
|
-
return uniqueResults.slice(0, 10); // Limit to top 10
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
export default {
|
|
203
|
-
searchGrep
|
|
204
|
-
};
|
|
1
|
+
/**
|
|
2
|
+
* Troubleshoot Grep Fallback
|
|
3
|
+
* Searches markdown files for matching content when index doesn't find results
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { readFileSync, readdirSync, existsSync } from 'fs';
|
|
7
|
+
import { join, dirname, basename } from 'path';
|
|
8
|
+
import { fileURLToPath } from 'url';
|
|
9
|
+
import { resolveStandardsDir } from '../stacks/stack-resolver.js';
|
|
10
|
+
|
|
11
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
12
|
+
const __dirname = dirname(__filename);
|
|
13
|
+
const frameworkRoot = join(__dirname, '..', '..');
|
|
14
|
+
|
|
15
|
+
// Directories to search (stack standards resolved dynamically)
|
|
16
|
+
const SEARCH_PATHS = [
|
|
17
|
+
'framework/standards',
|
|
18
|
+
'.wiki'
|
|
19
|
+
];
|
|
20
|
+
|
|
21
|
+
function getSearchPaths(basePath) {
|
|
22
|
+
const paths = [...SEARCH_PATHS];
|
|
23
|
+
// Insert resolved stack standards path
|
|
24
|
+
const stackStandards = resolveStandardsDir(basePath || frameworkRoot);
|
|
25
|
+
const relativePath = stackStandards.replace(basePath || frameworkRoot, '').replace(/^[\\/]/, '');
|
|
26
|
+
paths.splice(1, 0, relativePath);
|
|
27
|
+
return paths;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Get all markdown files from search paths
|
|
32
|
+
* @param {string} basePath - Base path of the project
|
|
33
|
+
* @returns {string[]} Array of file paths
|
|
34
|
+
*/
|
|
35
|
+
function getMarkdownFiles(basePath) {
|
|
36
|
+
const files = [];
|
|
37
|
+
|
|
38
|
+
for (const searchPath of getSearchPaths(basePath)) {
|
|
39
|
+
const fullPath = join(basePath, searchPath);
|
|
40
|
+
|
|
41
|
+
if (!existsSync(fullPath)) {
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
try {
|
|
46
|
+
const entries = readdirSync(fullPath, { withFileTypes: true });
|
|
47
|
+
|
|
48
|
+
for (const entry of entries) {
|
|
49
|
+
if (entry.isFile() && entry.name.endsWith('.md')) {
|
|
50
|
+
files.push(join(fullPath, entry.name));
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
} catch (error) {
|
|
54
|
+
// Skip directories we can't read
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return files;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Extract section containing the match
|
|
63
|
+
* @param {string} content - File content
|
|
64
|
+
* @param {number} matchIndex - Index of the match
|
|
65
|
+
* @returns {Object} Section object with title and content
|
|
66
|
+
*/
|
|
67
|
+
function extractSection(content, matchIndex) {
|
|
68
|
+
const lines = content.split('\n');
|
|
69
|
+
let charCount = 0;
|
|
70
|
+
let matchLineIndex = 0;
|
|
71
|
+
|
|
72
|
+
// Find the line containing the match
|
|
73
|
+
for (let i = 0; i < lines.length; i++) {
|
|
74
|
+
charCount += lines[i].length + 1; // +1 for newline
|
|
75
|
+
if (charCount > matchIndex) {
|
|
76
|
+
matchLineIndex = i;
|
|
77
|
+
break;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// Find the section header (## heading) above the match
|
|
82
|
+
let sectionTitle = 'Unknown Section';
|
|
83
|
+
let sectionStart = 0;
|
|
84
|
+
|
|
85
|
+
for (let i = matchLineIndex; i >= 0; i--) {
|
|
86
|
+
if (lines[i].startsWith('## ')) {
|
|
87
|
+
sectionTitle = lines[i].replace('## ', '').trim();
|
|
88
|
+
sectionStart = i;
|
|
89
|
+
break;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// Find the end of the section (next ## or end of file)
|
|
94
|
+
let sectionEnd = lines.length;
|
|
95
|
+
for (let i = sectionStart + 1; i < lines.length; i++) {
|
|
96
|
+
if (lines[i].startsWith('## ')) {
|
|
97
|
+
sectionEnd = i;
|
|
98
|
+
break;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// Extract section content (limit to ~20 lines around match)
|
|
103
|
+
const contextStart = Math.max(sectionStart, matchLineIndex - 10);
|
|
104
|
+
const contextEnd = Math.min(sectionEnd, matchLineIndex + 10);
|
|
105
|
+
const sectionContent = lines.slice(contextStart, contextEnd).join('\n');
|
|
106
|
+
|
|
107
|
+
return {
|
|
108
|
+
title: sectionTitle,
|
|
109
|
+
content: sectionContent,
|
|
110
|
+
lineNumber: matchLineIndex + 1
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Search a file for keywords
|
|
116
|
+
* @param {string} filePath - Path to the file
|
|
117
|
+
* @param {string[]} keywords - Keywords to search for
|
|
118
|
+
* @returns {Object[]} Array of matches
|
|
119
|
+
*/
|
|
120
|
+
function searchFile(filePath, keywords) {
|
|
121
|
+
const matches = [];
|
|
122
|
+
|
|
123
|
+
try {
|
|
124
|
+
const content = readFileSync(filePath, 'utf-8');
|
|
125
|
+
const contentLower = content.toLowerCase();
|
|
126
|
+
|
|
127
|
+
for (const keyword of keywords) {
|
|
128
|
+
const keywordLower = keyword.toLowerCase();
|
|
129
|
+
let index = contentLower.indexOf(keywordLower);
|
|
130
|
+
|
|
131
|
+
while (index !== -1) {
|
|
132
|
+
const section = extractSection(content, index);
|
|
133
|
+
|
|
134
|
+
// Check if we already have a match for this section
|
|
135
|
+
const existingMatch = matches.find(m => m.section === section.title);
|
|
136
|
+
|
|
137
|
+
if (existingMatch) {
|
|
138
|
+
existingMatch.matchCount++;
|
|
139
|
+
existingMatch.keywords.add(keyword);
|
|
140
|
+
} else {
|
|
141
|
+
matches.push({
|
|
142
|
+
file: filePath,
|
|
143
|
+
fileName: basename(filePath),
|
|
144
|
+
section: section.title,
|
|
145
|
+
content: section.content,
|
|
146
|
+
lineNumber: section.lineNumber,
|
|
147
|
+
matchCount: 1,
|
|
148
|
+
keywords: new Set([keyword])
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
index = contentLower.indexOf(keywordLower, index + 1);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
} catch (error) {
|
|
156
|
+
// Skip files we can't read
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
return matches;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Search all markdown files for keywords
|
|
164
|
+
* @param {string[]} keywords - Keywords to search for
|
|
165
|
+
* @param {Object} options - Search options
|
|
166
|
+
* @returns {Object[]} Array of matches sorted by relevance
|
|
167
|
+
*/
|
|
168
|
+
export function searchGrep(keywords, options = {}) {
|
|
169
|
+
// Determine base path
|
|
170
|
+
const basePath = options.basePath || join(__dirname, '../..');
|
|
171
|
+
|
|
172
|
+
const files = getMarkdownFiles(basePath);
|
|
173
|
+
let allMatches = [];
|
|
174
|
+
|
|
175
|
+
for (const file of files) {
|
|
176
|
+
const matches = searchFile(file, keywords);
|
|
177
|
+
allMatches = allMatches.concat(matches);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
// Convert keywords Set to Array and calculate score
|
|
181
|
+
const results = allMatches.map(match => ({
|
|
182
|
+
...match,
|
|
183
|
+
keywords: Array.from(match.keywords),
|
|
184
|
+
score: match.matchCount * 5 + match.keywords.size * 3,
|
|
185
|
+
source: 'grep'
|
|
186
|
+
}));
|
|
187
|
+
|
|
188
|
+
// Sort by score (higher is better) and deduplicate
|
|
189
|
+
const seen = new Set();
|
|
190
|
+
const uniqueResults = results
|
|
191
|
+
.sort((a, b) => b.score - a.score)
|
|
192
|
+
.filter(r => {
|
|
193
|
+
const key = `${r.file}:${r.section}`;
|
|
194
|
+
if (seen.has(key)) return false;
|
|
195
|
+
seen.add(key);
|
|
196
|
+
return true;
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
return uniqueResults.slice(0, 10); // Limit to top 10
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
export default {
|
|
203
|
+
searchGrep
|
|
204
|
+
};
|