prjct-cli 1.22.0 ā 1.23.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/CHANGELOG.md +147 -0
- package/bin/prjct +30 -13
- package/dist/bin/prjct.mjs +917 -35845
- package/dist/bin/prjct.mjs.map +7 -0
- package/dist/cli/linear.mjs +16 -0
- package/dist/cli/linear.mjs.map +7 -0
- package/dist/templates.json +1 -0
- package/package.json +4 -5
- package/bin/prjct.ts +0 -342
- package/core/__tests__/agentic/analysis-injection.test.ts +0 -377
- package/core/__tests__/agentic/cache-eviction.test.ts +0 -294
- package/core/__tests__/agentic/command-context.test.ts +0 -281
- package/core/__tests__/agentic/command-executor.test.ts +0 -659
- package/core/__tests__/agentic/domain-classifier.test.ts +0 -330
- package/core/__tests__/agentic/injection-validator.test.ts +0 -255
- package/core/__tests__/agentic/memory-system.test.ts +0 -281
- package/core/__tests__/agentic/plan-mode.test.ts +0 -386
- package/core/__tests__/agentic/prompt-assembly.test.ts +0 -298
- package/core/__tests__/agentic/prompt-builder.test.ts +0 -243
- package/core/__tests__/agentic/response-validator.test.ts +0 -263
- package/core/__tests__/agentic/semantic-matching.test.ts +0 -131
- package/core/__tests__/agentic/smart-context.test.ts +0 -372
- package/core/__tests__/agentic/tech-normalizer.test.ts +0 -136
- package/core/__tests__/agentic/token-budget.test.ts +0 -294
- package/core/__tests__/ai-tools/formatters.test.ts +0 -476
- package/core/__tests__/domain/bm25.test.ts +0 -225
- package/core/__tests__/domain/change-propagator.test.ts +0 -100
- package/core/__tests__/domain/fibonacci.test.ts +0 -113
- package/core/__tests__/domain/file-hasher.test.ts +0 -146
- package/core/__tests__/domain/file-ranker.test.ts +0 -169
- package/core/__tests__/domain/git-cochange.test.ts +0 -121
- package/core/__tests__/domain/import-graph.test.ts +0 -156
- package/core/__tests__/domain/velocity.test.ts +0 -623
- package/core/__tests__/infrastructure/performance-tracker.test.ts +0 -328
- package/core/__tests__/schemas/model.test.ts +0 -272
- package/core/__tests__/services/dependency-validator.test.ts +0 -175
- package/core/__tests__/services/hierarchical-agent-resolver.test.ts +0 -359
- package/core/__tests__/services/nested-context-resolver.test.ts +0 -443
- package/core/__tests__/services/project-index.test.ts +0 -355
- package/core/__tests__/services/staleness-checker.test.ts +0 -204
- package/core/__tests__/storage/analysis-storage.test.ts +0 -641
- package/core/__tests__/storage/archive-storage.test.ts +0 -455
- package/core/__tests__/storage/safe-reader.test.ts +0 -262
- package/core/__tests__/storage/sqlite-migration.test.ts +0 -1016
- package/core/__tests__/storage/state-storage-feedback.test.ts +0 -463
- package/core/__tests__/storage/state-storage-history.test.ts +0 -469
- package/core/__tests__/storage/storage-manager.test.ts +0 -383
- package/core/__tests__/storage/subtask-handoff.test.ts +0 -237
- package/core/__tests__/types/fs.test.ts +0 -125
- package/core/__tests__/utils/date-helper.test.ts +0 -449
- package/core/__tests__/utils/output.test.ts +0 -278
- package/core/__tests__/utils/preserve-sections.test.ts +0 -216
- package/core/__tests__/utils/project-commands.test.ts +0 -71
- package/core/__tests__/utils/retry.test.ts +0 -381
- package/core/__tests__/workflow/state-machine.test.ts +0 -216
- package/core/agentic/agent-router.ts +0 -150
- package/core/agentic/anti-hallucination.ts +0 -141
- package/core/agentic/chain-of-thought.ts +0 -234
- package/core/agentic/command-classifier.ts +0 -141
- package/core/agentic/command-context.ts +0 -168
- package/core/agentic/command-executor.ts +0 -471
- package/core/agentic/context-builder.ts +0 -285
- package/core/agentic/domain-classifier.ts +0 -525
- package/core/agentic/environment-block.ts +0 -102
- package/core/agentic/ground-truth.ts +0 -706
- package/core/agentic/index.ts +0 -193
- package/core/agentic/injection-validator.ts +0 -208
- package/core/agentic/loop-detector.ts +0 -451
- package/core/agentic/memory-system.ts +0 -1547
- package/core/agentic/orchestrator-executor.ts +0 -579
- package/core/agentic/plan-mode.ts +0 -525
- package/core/agentic/prompt-builder.ts +0 -1069
- package/core/agentic/response-validator.ts +0 -98
- package/core/agentic/services.ts +0 -167
- package/core/agentic/skill-loader.ts +0 -106
- package/core/agentic/smart-context.ts +0 -393
- package/core/agentic/tech-normalizer.ts +0 -167
- package/core/agentic/template-executor.ts +0 -272
- package/core/agentic/template-loader.ts +0 -109
- package/core/agentic/token-budget.ts +0 -226
- package/core/agentic/tool-registry.ts +0 -146
- package/core/agents/index.ts +0 -28
- package/core/agents/performance.ts +0 -429
- package/core/ai-tools/formatters.ts +0 -341
- package/core/ai-tools/generator.ts +0 -144
- package/core/ai-tools/index.ts +0 -15
- package/core/ai-tools/registry.ts +0 -201
- package/core/bus/bus.ts +0 -314
- package/core/bus/index.ts +0 -8
- package/core/cli/linear.ts +0 -500
- package/core/cli/lint-meta-commentary.ts +0 -177
- package/core/cli/start.ts +0 -386
- package/core/commands/analysis.ts +0 -1274
- package/core/commands/analytics.ts +0 -342
- package/core/commands/base.ts +0 -118
- package/core/commands/cleanup.ts +0 -157
- package/core/commands/command-data.ts +0 -463
- package/core/commands/commands.ts +0 -306
- package/core/commands/context.ts +0 -238
- package/core/commands/design.ts +0 -77
- package/core/commands/index.ts +0 -19
- package/core/commands/maintenance.ts +0 -77
- package/core/commands/performance.ts +0 -114
- package/core/commands/planning.ts +0 -662
- package/core/commands/register.ts +0 -127
- package/core/commands/registry.ts +0 -444
- package/core/commands/setup.ts +0 -280
- package/core/commands/shipping.ts +0 -267
- package/core/commands/snapshots.ts +0 -297
- package/core/commands/uninstall.ts +0 -542
- package/core/commands/velocity.ts +0 -149
- package/core/commands/workflow.ts +0 -505
- package/core/config/command-context.config.json +0 -66
- package/core/constants/index.ts +0 -379
- package/core/context/generator.ts +0 -368
- package/core/context-tools/files-tool.ts +0 -577
- package/core/context-tools/imports-tool.ts +0 -400
- package/core/context-tools/index.ts +0 -434
- package/core/context-tools/recent-tool.ts +0 -301
- package/core/context-tools/signatures-tool.ts +0 -495
- package/core/context-tools/summary-tool.ts +0 -301
- package/core/context-tools/token-counter.ts +0 -273
- package/core/context-tools/types.ts +0 -253
- package/core/domain/agent-generator.ts +0 -186
- package/core/domain/agent-loader.ts +0 -419
- package/core/domain/analyzer.ts +0 -387
- package/core/domain/architecture-generator.ts +0 -108
- package/core/domain/bm25.ts +0 -525
- package/core/domain/change-propagator.ts +0 -162
- package/core/domain/context-estimator.ts +0 -175
- package/core/domain/fibonacci.ts +0 -128
- package/core/domain/file-hasher.ts +0 -296
- package/core/domain/file-ranker.ts +0 -151
- package/core/domain/git-cochange.ts +0 -250
- package/core/domain/import-graph.ts +0 -315
- package/core/domain/snapshot-manager.ts +0 -415
- package/core/domain/task-stack.ts +0 -578
- package/core/domain/velocity.ts +0 -470
- package/core/errors.ts +0 -335
- package/core/events/events.ts +0 -85
- package/core/events/index.ts +0 -8
- package/core/index.ts +0 -481
- package/core/infrastructure/agent-detector.ts +0 -135
- package/core/infrastructure/ai-provider.ts +0 -578
- package/core/infrastructure/author-detector.ts +0 -133
- package/core/infrastructure/capability-installer.ts +0 -76
- package/core/infrastructure/claude-agent.ts +0 -297
- package/core/infrastructure/command-installer.ts +0 -752
- package/core/infrastructure/config-manager.ts +0 -364
- package/core/infrastructure/editors-config.ts +0 -172
- package/core/infrastructure/path-manager.ts +0 -571
- package/core/infrastructure/performance-tracker.ts +0 -326
- package/core/infrastructure/permission-manager.ts +0 -289
- package/core/infrastructure/setup.ts +0 -1061
- package/core/infrastructure/update-checker.ts +0 -246
- package/core/integrations/issue-tracker/enricher.ts +0 -271
- package/core/integrations/issue-tracker/index.ts +0 -8
- package/core/integrations/issue-tracker/manager.ts +0 -286
- package/core/integrations/issue-tracker/types.ts +0 -310
- package/core/integrations/jira/cache.ts +0 -57
- package/core/integrations/jira/client.ts +0 -688
- package/core/integrations/jira/index.ts +0 -23
- package/core/integrations/jira/service.ts +0 -244
- package/core/integrations/linear/cache.ts +0 -68
- package/core/integrations/linear/client.ts +0 -436
- package/core/integrations/linear/index.ts +0 -20
- package/core/integrations/linear/service.ts +0 -260
- package/core/integrations/linear/sync.ts +0 -314
- package/core/outcomes/analyzer.ts +0 -286
- package/core/outcomes/index.ts +0 -34
- package/core/outcomes/recorder.ts +0 -195
- package/core/plugin/builtin/webhook.ts +0 -148
- package/core/plugin/hooks.ts +0 -315
- package/core/plugin/index.ts +0 -50
- package/core/plugin/loader.ts +0 -354
- package/core/plugin/registry.ts +0 -326
- package/core/schemas/agents.ts +0 -27
- package/core/schemas/analysis.ts +0 -530
- package/core/schemas/classification.ts +0 -91
- package/core/schemas/command-context.ts +0 -29
- package/core/schemas/enriched-task.ts +0 -291
- package/core/schemas/ideas.ts +0 -114
- package/core/schemas/index.ts +0 -53
- package/core/schemas/issues.ts +0 -159
- package/core/schemas/llm-output.ts +0 -170
- package/core/schemas/metrics.ts +0 -143
- package/core/schemas/model.ts +0 -153
- package/core/schemas/outcomes.ts +0 -487
- package/core/schemas/performance.ts +0 -128
- package/core/schemas/permissions.ts +0 -180
- package/core/schemas/prd.ts +0 -450
- package/core/schemas/project.ts +0 -57
- package/core/schemas/roadmap.ts +0 -322
- package/core/schemas/schemas.ts +0 -38
- package/core/schemas/shipped.ts +0 -109
- package/core/schemas/state.ts +0 -284
- package/core/schemas/velocity.ts +0 -103
- package/core/server/index.ts +0 -21
- package/core/server/routes-extended.ts +0 -566
- package/core/server/routes.ts +0 -176
- package/core/server/server.ts +0 -149
- package/core/server/sse.ts +0 -192
- package/core/services/agent-generator.ts +0 -385
- package/core/services/agent-service.ts +0 -168
- package/core/services/breakdown-service.ts +0 -124
- package/core/services/context-generator.ts +0 -445
- package/core/services/context-selector.ts +0 -429
- package/core/services/dependency-validator.ts +0 -318
- package/core/services/diff-generator.ts +0 -313
- package/core/services/doctor-service.ts +0 -423
- package/core/services/file-categorizer.ts +0 -448
- package/core/services/file-scorer.ts +0 -270
- package/core/services/git-analyzer.ts +0 -293
- package/core/services/hierarchical-agent-resolver.ts +0 -236
- package/core/services/hooks-service.ts +0 -685
- package/core/services/index.ts +0 -46
- package/core/services/local-state-generator.ts +0 -158
- package/core/services/memory-service.ts +0 -181
- package/core/services/nested-context-resolver.ts +0 -842
- package/core/services/project-index.ts +0 -911
- package/core/services/project-service.ts +0 -155
- package/core/services/session-tracker.ts +0 -287
- package/core/services/skill-installer.ts +0 -447
- package/core/services/skill-lock.ts +0 -132
- package/core/services/skill-service.ts +0 -306
- package/core/services/stack-detector.ts +0 -229
- package/core/services/staleness-checker.ts +0 -327
- package/core/services/sync-service.ts +0 -1515
- package/core/services/sync-verifier.ts +0 -253
- package/core/services/watch-service.ts +0 -312
- package/core/session/compaction.ts +0 -248
- package/core/session/index.ts +0 -35
- package/core/session/log-migration.ts +0 -88
- package/core/session/metrics.ts +0 -323
- package/core/session/session-log-manager.ts +0 -307
- package/core/session/task-session-manager.ts +0 -404
- package/core/session/utils.ts +0 -51
- package/core/storage/analysis-storage.ts +0 -373
- package/core/storage/archive-storage.ts +0 -205
- package/core/storage/database.ts +0 -575
- package/core/storage/ideas-storage.ts +0 -298
- package/core/storage/index-storage.ts +0 -523
- package/core/storage/index.ts +0 -79
- package/core/storage/metrics-storage.ts +0 -321
- package/core/storage/migrate-json.ts +0 -720
- package/core/storage/queue-storage.ts +0 -336
- package/core/storage/safe-reader.ts +0 -105
- package/core/storage/shipped-storage.ts +0 -253
- package/core/storage/state-storage.ts +0 -1035
- package/core/storage/storage-manager.ts +0 -205
- package/core/storage/storage.ts +0 -177
- package/core/storage/velocity-storage.ts +0 -149
- package/core/sync/auth-config.ts +0 -138
- package/core/sync/index.ts +0 -31
- package/core/sync/oauth-handler.ts +0 -143
- package/core/sync/sync-client.ts +0 -251
- package/core/sync/sync-manager.ts +0 -327
- package/core/tsconfig.json +0 -22
- package/core/types/agentic.ts +0 -760
- package/core/types/agents.ts +0 -150
- package/core/types/bus.ts +0 -193
- package/core/types/citations.ts +0 -22
- package/core/types/commands.ts +0 -399
- package/core/types/config.ts +0 -92
- package/core/types/core.ts +0 -96
- package/core/types/diff.ts +0 -41
- package/core/types/domain.ts +0 -71
- package/core/types/errors.ts +0 -111
- package/core/types/events.ts +0 -42
- package/core/types/fs.ts +0 -72
- package/core/types/index.ts +0 -510
- package/core/types/infrastructure.ts +0 -210
- package/core/types/integrations.ts +0 -31
- package/core/types/jira.ts +0 -51
- package/core/types/logger.ts +0 -17
- package/core/types/memory.ts +0 -313
- package/core/types/outcomes.ts +0 -190
- package/core/types/output.ts +0 -47
- package/core/types/plugin.ts +0 -25
- package/core/types/project-sync.ts +0 -129
- package/core/types/provider.ts +0 -163
- package/core/types/server.ts +0 -71
- package/core/types/services.ts +0 -84
- package/core/types/session.ts +0 -135
- package/core/types/stack.ts +0 -19
- package/core/types/storage.ts +0 -318
- package/core/types/sync-verifier.ts +0 -33
- package/core/types/sync.ts +0 -121
- package/core/types/task.ts +0 -72
- package/core/types/template.ts +0 -24
- package/core/types/utils.ts +0 -92
- package/core/types/workflow.ts +0 -23
- package/core/utils/agent-stream.ts +0 -140
- package/core/utils/animations.ts +0 -251
- package/core/utils/branding.ts +0 -88
- package/core/utils/cache.ts +0 -187
- package/core/utils/citations.ts +0 -39
- package/core/utils/collection-filters.ts +0 -209
- package/core/utils/date-helper.ts +0 -176
- package/core/utils/error-messages.ts +0 -38
- package/core/utils/file-helper.ts +0 -277
- package/core/utils/fs-helpers.ts +0 -14
- package/core/utils/help.ts +0 -314
- package/core/utils/jsonl-helper.ts +0 -290
- package/core/utils/keychain.ts +0 -127
- package/core/utils/logger.ts +0 -77
- package/core/utils/markdown-builder.ts +0 -280
- package/core/utils/next-steps.ts +0 -95
- package/core/utils/output.ts +0 -403
- package/core/utils/preserve-sections.ts +0 -218
- package/core/utils/project-commands.ts +0 -126
- package/core/utils/project-credentials.ts +0 -143
- package/core/utils/provider-cache.ts +0 -49
- package/core/utils/retry.ts +0 -318
- package/core/utils/runtime.ts +0 -108
- package/core/utils/session-helper.ts +0 -278
- package/core/utils/subtask-table.ts +0 -227
- package/core/utils/version.ts +0 -128
- package/core/wizard/index.ts +0 -13
- package/core/wizard/onboarding.ts +0 -633
- package/core/workflow/index.ts +0 -7
- package/core/workflow/state-machine.ts +0 -198
- package/core/workflow/workflow-preferences.ts +0 -294
- package/dist/core/infrastructure/command-installer.js +0 -1141
- package/dist/core/infrastructure/editors-config.js +0 -177
- package/dist/core/infrastructure/setup.js +0 -2244
- package/dist/core/utils/version.js +0 -141
- package/templates/agentic/agent-routing.md +0 -45
- package/templates/agentic/agents/uxui.md +0 -63
- package/templates/agentic/checklist-routing.md +0 -98
- package/templates/agentic/orchestrator.md +0 -68
- package/templates/agentic/task-fragmentation.md +0 -89
- package/templates/agents/AGENTS.md +0 -68
- package/templates/analysis/analyze.md +0 -84
- package/templates/analysis/patterns.md +0 -60
- package/templates/antigravity/SKILL.md +0 -39
- package/templates/architect/discovery.md +0 -67
- package/templates/architect/phases.md +0 -59
- package/templates/checklists/architecture.md +0 -28
- package/templates/checklists/code-quality.md +0 -28
- package/templates/checklists/data.md +0 -33
- package/templates/checklists/documentation.md +0 -33
- package/templates/checklists/infrastructure.md +0 -33
- package/templates/checklists/performance.md +0 -33
- package/templates/checklists/security.md +0 -33
- package/templates/checklists/testing.md +0 -33
- package/templates/checklists/ux-ui.md +0 -37
- package/templates/commands/analyze.md +0 -56
- package/templates/commands/auth.md +0 -234
- package/templates/commands/bug.md +0 -163
- package/templates/commands/cleanup.md +0 -19
- package/templates/commands/dash.md +0 -99
- package/templates/commands/design.md +0 -15
- package/templates/commands/done.md +0 -291
- package/templates/commands/enrich.md +0 -174
- package/templates/commands/git.md +0 -295
- package/templates/commands/history.md +0 -389
- package/templates/commands/idea.md +0 -88
- package/templates/commands/impact.md +0 -864
- package/templates/commands/init.md +0 -54
- package/templates/commands/jira.md +0 -278
- package/templates/commands/linear.md +0 -288
- package/templates/commands/merge.md +0 -206
- package/templates/commands/next.md +0 -80
- package/templates/commands/p.md +0 -67
- package/templates/commands/p.toml +0 -37
- package/templates/commands/pause.md +0 -136
- package/templates/commands/plan.md +0 -696
- package/templates/commands/prd.md +0 -356
- package/templates/commands/resume.md +0 -171
- package/templates/commands/review.md +0 -276
- package/templates/commands/serve.md +0 -118
- package/templates/commands/setup.md +0 -91
- package/templates/commands/ship.md +0 -475
- package/templates/commands/skill.md +0 -259
- package/templates/commands/spec.md +0 -218
- package/templates/commands/status.md +0 -207
- package/templates/commands/sync.md +0 -104
- package/templates/commands/task.md +0 -312
- package/templates/commands/test.md +0 -93
- package/templates/commands/update.md +0 -63
- package/templates/commands/verify.md +0 -204
- package/templates/commands/workflow.md +0 -150
- package/templates/config/skill-mappings.json +0 -82
- package/templates/context/dashboard.md +0 -256
- package/templates/context/roadmap.md +0 -221
- package/templates/cursor/commands/bug.md +0 -8
- package/templates/cursor/commands/done.md +0 -4
- package/templates/cursor/commands/pause.md +0 -6
- package/templates/cursor/commands/resume.md +0 -4
- package/templates/cursor/commands/ship.md +0 -8
- package/templates/cursor/commands/sync.md +0 -4
- package/templates/cursor/commands/task.md +0 -8
- package/templates/cursor/p.md +0 -29
- package/templates/cursor/router.mdc +0 -28
- package/templates/design/api.md +0 -95
- package/templates/design/architecture.md +0 -77
- package/templates/design/component.md +0 -89
- package/templates/design/database.md +0 -78
- package/templates/design/flow.md +0 -94
- package/templates/global/ANTIGRAVITY.md +0 -254
- package/templates/global/CLAUDE.md +0 -497
- package/templates/global/CURSOR.mdc +0 -266
- package/templates/global/GEMINI.md +0 -293
- package/templates/global/STORAGE-SPEC.md +0 -391
- package/templates/global/WINDSURF.md +0 -266
- package/templates/global/modules/CLAUDE-commands.md +0 -70
- package/templates/global/modules/CLAUDE-core.md +0 -105
- package/templates/global/modules/CLAUDE-git.md +0 -50
- package/templates/global/modules/CLAUDE-intelligence.md +0 -92
- package/templates/global/modules/CLAUDE-storage.md +0 -50
- package/templates/global/modules/module-config.json +0 -36
- package/templates/mcp-config.json +0 -19
- package/templates/permissions/default.jsonc +0 -60
- package/templates/permissions/permissive.jsonc +0 -49
- package/templates/permissions/strict.jsonc +0 -58
- package/templates/planning-methodology.md +0 -195
- package/templates/skills/code-review.md +0 -47
- package/templates/skills/debug.md +0 -61
- package/templates/skills/refactor.md +0 -47
- package/templates/subagents/agent-base.md +0 -20
- package/templates/subagents/domain/backend.md +0 -109
- package/templates/subagents/domain/database.md +0 -121
- package/templates/subagents/domain/devops.md +0 -152
- package/templates/subagents/domain/frontend.md +0 -103
- package/templates/subagents/domain/testing.md +0 -169
- package/templates/subagents/pm-expert.md +0 -366
- package/templates/subagents/workflow/chief-architect.md +0 -657
- package/templates/subagents/workflow/prjct-planner.md +0 -159
- package/templates/subagents/workflow/prjct-shipper.md +0 -188
- package/templates/subagents/workflow/prjct-workflow.md +0 -98
- package/templates/tools/bash.txt +0 -22
- package/templates/tools/edit.txt +0 -18
- package/templates/tools/glob.txt +0 -19
- package/templates/tools/grep.txt +0 -21
- package/templates/tools/read.txt +0 -14
- package/templates/tools/task.txt +0 -20
- package/templates/tools/webfetch.txt +0 -16
- package/templates/tools/websearch.txt +0 -18
- package/templates/tools/write.txt +0 -17
- package/templates/windsurf/router.md +0 -28
- package/templates/windsurf/workflows/bug.md +0 -8
- package/templates/windsurf/workflows/done.md +0 -4
- package/templates/windsurf/workflows/pause.md +0 -4
- package/templates/windsurf/workflows/resume.md +0 -4
- package/templates/windsurf/workflows/ship.md +0 -8
- package/templates/windsurf/workflows/sync.md +0 -4
- package/templates/windsurf/workflows/task.md +0 -8
|
@@ -1,662 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Planning Commands: init, feature, bug, idea, spec
|
|
3
|
-
* Write-Through Architecture: JSON ā MD ā Event
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import path from 'node:path'
|
|
7
|
-
import * as authorDetector from '../infrastructure/author-detector'
|
|
8
|
-
import commandInstaller from '../infrastructure/command-installer'
|
|
9
|
-
import { generateUUID } from '../schemas'
|
|
10
|
-
import type { Priority, TaskSection, TaskType } from '../schemas/state'
|
|
11
|
-
import { ideasStorage, queueStorage } from '../storage'
|
|
12
|
-
import type { CommandResult, InitOptions, ProjectContext } from '../types'
|
|
13
|
-
import { getErrorMessage } from '../types/fs'
|
|
14
|
-
import { showNextSteps } from '../utils/next-steps'
|
|
15
|
-
import { OnboardingWizard } from '../wizard'
|
|
16
|
-
import {
|
|
17
|
-
configManager,
|
|
18
|
-
contextBuilder,
|
|
19
|
-
dateHelper,
|
|
20
|
-
fileHelper,
|
|
21
|
-
out,
|
|
22
|
-
PrjctCommandsBase,
|
|
23
|
-
pathManager,
|
|
24
|
-
toolRegistry,
|
|
25
|
-
} from './base'
|
|
26
|
-
|
|
27
|
-
// Lazy-loaded to avoid circular dependencies
|
|
28
|
-
let _analysisCommands: import('./analysis').AnalysisCommands | null = null
|
|
29
|
-
async function getAnalysisCommands(): Promise<import('./analysis').AnalysisCommands> {
|
|
30
|
-
if (!_analysisCommands) {
|
|
31
|
-
const { AnalysisCommands } = await import('./analysis')
|
|
32
|
-
_analysisCommands = new AnalysisCommands()
|
|
33
|
-
}
|
|
34
|
-
return _analysisCommands
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
export type { InitOptions } from '../types'
|
|
38
|
-
|
|
39
|
-
export class PlanningCommands extends PrjctCommandsBase {
|
|
40
|
-
/**
|
|
41
|
-
* /p:init - Initialize prjct project with interactive wizard
|
|
42
|
-
*
|
|
43
|
-
* @param options.yes - Skip wizard, use auto-detected values (for CI)
|
|
44
|
-
* @param options.idea - Initial idea for architect mode
|
|
45
|
-
* @param projectPath - Project directory path
|
|
46
|
-
*/
|
|
47
|
-
async init(
|
|
48
|
-
options: InitOptions | string | null = {},
|
|
49
|
-
projectPath: string = process.cwd()
|
|
50
|
-
): Promise<CommandResult> {
|
|
51
|
-
try {
|
|
52
|
-
// Handle legacy signature: init(idea, projectPath)
|
|
53
|
-
let opts: InitOptions = {}
|
|
54
|
-
if (typeof options === 'string' || options === null) {
|
|
55
|
-
opts = { idea: options }
|
|
56
|
-
} else {
|
|
57
|
-
opts = options
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
await this.initializeAgent()
|
|
61
|
-
|
|
62
|
-
const isConfigured = await configManager.isConfigured(projectPath)
|
|
63
|
-
|
|
64
|
-
if (isConfigured) {
|
|
65
|
-
out.warn('already initialized')
|
|
66
|
-
return { success: false, message: 'Already initialized' }
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
// Determine if we should run interactive wizard
|
|
70
|
-
const isTTY = process.stdout.isTTY && process.stdin.isTTY
|
|
71
|
-
// CI: Skip interactive prompts in CI environments
|
|
72
|
-
const skipWizard = opts.yes || !isTTY || process.env.CI === 'true'
|
|
73
|
-
|
|
74
|
-
// Run wizard if interactive
|
|
75
|
-
let wizardResult = null
|
|
76
|
-
if (!skipWizard) {
|
|
77
|
-
const wizard = new OnboardingWizard(projectPath)
|
|
78
|
-
wizardResult = await wizard.run()
|
|
79
|
-
|
|
80
|
-
if (wizardResult.skipped) {
|
|
81
|
-
return { success: false, message: 'Setup cancelled' }
|
|
82
|
-
}
|
|
83
|
-
} else if (isTTY && opts.yes) {
|
|
84
|
-
// Non-interactive but show progress
|
|
85
|
-
const wizard = new OnboardingWizard(projectPath)
|
|
86
|
-
wizardResult = await wizard.runNonInteractive()
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
out.step(1, 4, 'Detecting author...')
|
|
90
|
-
|
|
91
|
-
const detectedAuthor = await authorDetector.detect()
|
|
92
|
-
// Convert null to undefined for createConfig
|
|
93
|
-
const author = {
|
|
94
|
-
name: detectedAuthor.name || undefined,
|
|
95
|
-
email: detectedAuthor.email || undefined,
|
|
96
|
-
github: detectedAuthor.github || undefined,
|
|
97
|
-
}
|
|
98
|
-
const config = await configManager.createConfig(projectPath, author)
|
|
99
|
-
const projectId = config.projectId
|
|
100
|
-
|
|
101
|
-
out.step(2, 4, 'Creating structure...')
|
|
102
|
-
|
|
103
|
-
await pathManager.ensureProjectStructure(projectId)
|
|
104
|
-
const globalPath = pathManager.getGlobalProjectPath(projectId)
|
|
105
|
-
|
|
106
|
-
const baseFiles: Record<string, string> = {
|
|
107
|
-
'core/now.md': '# NOW\n\nNo current task. Use `/p:now` to set focus.\n',
|
|
108
|
-
'core/next.md': '# NEXT\n\n## Priority Queue\n\n',
|
|
109
|
-
'core/context.md': '# CONTEXT\n\n',
|
|
110
|
-
'progress/shipped.md': '# SHIPPED š\n\n',
|
|
111
|
-
'progress/metrics.md': '# METRICS\n\n',
|
|
112
|
-
'planning/ideas.md': '# IDEAS š”\n\n## Brain Dump\n\n',
|
|
113
|
-
'planning/roadmap.md': '# ROADMAP\n\n',
|
|
114
|
-
'planning/specs/.gitkeep': '# Specs directory - created by /p:spec\n',
|
|
115
|
-
'memory/context.jsonl': '',
|
|
116
|
-
'memory/patterns.json': JSON.stringify(
|
|
117
|
-
{
|
|
118
|
-
version: 1,
|
|
119
|
-
decisions: {},
|
|
120
|
-
preferences: {},
|
|
121
|
-
workflows: {},
|
|
122
|
-
counters: {},
|
|
123
|
-
},
|
|
124
|
-
null,
|
|
125
|
-
2
|
|
126
|
-
),
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
// Save wizard preferences if available
|
|
130
|
-
if (wizardResult) {
|
|
131
|
-
baseFiles['config/wizard.json'] = JSON.stringify(
|
|
132
|
-
{
|
|
133
|
-
projectType: wizardResult.projectType,
|
|
134
|
-
agents: wizardResult.agents,
|
|
135
|
-
stack: wizardResult.stack,
|
|
136
|
-
preferences: wizardResult.preferences,
|
|
137
|
-
createdAt: new Date().toISOString(),
|
|
138
|
-
},
|
|
139
|
-
null,
|
|
140
|
-
2
|
|
141
|
-
)
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
for (const [filePath, content] of Object.entries(baseFiles)) {
|
|
145
|
-
await toolRegistry.get('Write')!(path.join(globalPath, filePath), content)
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
const isEmpty = await this._detectEmptyDirectory(projectPath)
|
|
149
|
-
const hasCode = await this._detectExistingCode(projectPath)
|
|
150
|
-
|
|
151
|
-
if (hasCode || !isEmpty) {
|
|
152
|
-
out.step(3, 4, 'Analyzing project...')
|
|
153
|
-
const analysis = await getAnalysisCommands()
|
|
154
|
-
const analysisResult = await analysis.analyze({}, projectPath)
|
|
155
|
-
|
|
156
|
-
if (analysisResult.success) {
|
|
157
|
-
out.step(4, 4, 'Generating agents...')
|
|
158
|
-
|
|
159
|
-
// Pass wizard agent selection to sync if available
|
|
160
|
-
if (wizardResult?.agents) {
|
|
161
|
-
await analysis.sync(projectPath, { aiTools: wizardResult.agents })
|
|
162
|
-
} else {
|
|
163
|
-
await analysis.sync(projectPath)
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
out.done('initialized')
|
|
167
|
-
this._printNextSteps(wizardResult)
|
|
168
|
-
return { success: true, mode: 'existing', projectId, wizard: wizardResult }
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
const idea = opts.idea
|
|
173
|
-
if (isEmpty && !hasCode) {
|
|
174
|
-
if (!idea) {
|
|
175
|
-
out.done('blank project - provide idea for architect mode')
|
|
176
|
-
return { success: true, mode: 'blank_no_idea', projectId, wizard: wizardResult }
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
out.spin('architect mode...')
|
|
180
|
-
const sessionPath = path.join(globalPath, 'planning', 'architect-session.md')
|
|
181
|
-
const sessionContent = `# Architect Session\n\n## Idea\n${idea}\n\n## Status\nInitialized - awaiting stack recommendation\n\nGenerated: ${new Date().toLocaleString()}\n`
|
|
182
|
-
await toolRegistry.get('Write')!(sessionPath, sessionContent)
|
|
183
|
-
|
|
184
|
-
await commandInstaller.installGlobalConfig()
|
|
185
|
-
|
|
186
|
-
out.done('architect mode ready')
|
|
187
|
-
return { success: true, mode: 'architect', projectId, idea, wizard: wizardResult }
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
await commandInstaller.installGlobalConfig()
|
|
191
|
-
|
|
192
|
-
out.done('initialized')
|
|
193
|
-
this._printNextSteps(wizardResult)
|
|
194
|
-
return { success: true, projectId, wizard: wizardResult }
|
|
195
|
-
} catch (error) {
|
|
196
|
-
out.fail(getErrorMessage(error))
|
|
197
|
-
return { success: false, error: getErrorMessage(error) }
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
/**
|
|
202
|
-
* Print next steps after initialization
|
|
203
|
-
*/
|
|
204
|
-
private _printNextSteps(wizardResult: import('../wizard').WizardResult | null): void {
|
|
205
|
-
console.log('')
|
|
206
|
-
console.log(' Quick start:')
|
|
207
|
-
console.log(' prjct sync Update context after changes')
|
|
208
|
-
console.log(' prjct task Start working on a task')
|
|
209
|
-
console.log(' prjct hooks Auto-sync on commit/checkout')
|
|
210
|
-
console.log('')
|
|
211
|
-
|
|
212
|
-
if (wizardResult) {
|
|
213
|
-
const agentFiles = wizardResult.agents
|
|
214
|
-
.map((a) => {
|
|
215
|
-
switch (a) {
|
|
216
|
-
case 'claude':
|
|
217
|
-
return 'CLAUDE.md'
|
|
218
|
-
case 'cursor':
|
|
219
|
-
return '.cursorrules'
|
|
220
|
-
case 'windsurf':
|
|
221
|
-
return '.windsurfrules'
|
|
222
|
-
case 'copilot':
|
|
223
|
-
return '.github/copilot-instructions.md'
|
|
224
|
-
case 'gemini':
|
|
225
|
-
return 'GEMINI.md'
|
|
226
|
-
default:
|
|
227
|
-
return null
|
|
228
|
-
}
|
|
229
|
-
})
|
|
230
|
-
.filter(Boolean)
|
|
231
|
-
|
|
232
|
-
if (agentFiles.length > 0) {
|
|
233
|
-
console.log(` Generated: ${agentFiles.join(', ')}`)
|
|
234
|
-
console.log('')
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
console.log(' Docs: https://prjct.app/docs')
|
|
239
|
-
console.log('')
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
/**
|
|
243
|
-
* /p:feature - Add feature with value analysis, roadmap, and task breakdown
|
|
244
|
-
*/
|
|
245
|
-
async feature(description: string, projectPath: string = process.cwd()): Promise<CommandResult> {
|
|
246
|
-
try {
|
|
247
|
-
const initResult = await this.ensureProjectInit(projectPath)
|
|
248
|
-
if (!initResult.success) return initResult
|
|
249
|
-
|
|
250
|
-
if (!description) {
|
|
251
|
-
out.fail('description required')
|
|
252
|
-
return { success: false, error: 'Description required' }
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
const projectId = await configManager.getProjectId(projectPath)
|
|
256
|
-
if (!projectId) {
|
|
257
|
-
out.failWithHint('NO_PROJECT_ID')
|
|
258
|
-
return { success: false, error: 'No project ID found' }
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
out.spin(`planning ${description}...`)
|
|
262
|
-
|
|
263
|
-
const context = (await contextBuilder.build(projectPath, { description })) as ProjectContext
|
|
264
|
-
const tasks = this._breakdownFeatureTasks(description)
|
|
265
|
-
const featureId = generateUUID()
|
|
266
|
-
|
|
267
|
-
const tasksWithAgents: { task: string; agent: string }[] = []
|
|
268
|
-
for (const taskDesc of tasks) {
|
|
269
|
-
const agentResult = await this._assignAgentForTask(taskDesc, projectPath, context)
|
|
270
|
-
const agent = agentResult.agent?.name || 'generalist'
|
|
271
|
-
tasksWithAgents.push({ task: taskDesc, agent })
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
// Write-through: Add tasks (JSON ā MD ā Event)
|
|
275
|
-
await queueStorage.addTasks(
|
|
276
|
-
projectId,
|
|
277
|
-
tasksWithAgents.map((t) => ({
|
|
278
|
-
description: t.task,
|
|
279
|
-
priority: 'medium' as Priority,
|
|
280
|
-
type: 'feature' as TaskType,
|
|
281
|
-
section: 'active' as TaskSection,
|
|
282
|
-
featureId,
|
|
283
|
-
originFeature: description,
|
|
284
|
-
agent: t.agent,
|
|
285
|
-
}))
|
|
286
|
-
)
|
|
287
|
-
|
|
288
|
-
await this.logToMemory(projectPath, 'feature_planned', {
|
|
289
|
-
feature: description,
|
|
290
|
-
featureId,
|
|
291
|
-
tasks: tasksWithAgents.length,
|
|
292
|
-
assignments: tasksWithAgents.map((t) => ({ task: t.task, agent: t.agent })),
|
|
293
|
-
timestamp: dateHelper.getTimestamp(),
|
|
294
|
-
})
|
|
295
|
-
|
|
296
|
-
const agentCounts = tasksWithAgents.reduce((acc: Record<string, number>, t) => {
|
|
297
|
-
acc[t.agent] = (acc[t.agent] || 0) + 1
|
|
298
|
-
return acc
|
|
299
|
-
}, {})
|
|
300
|
-
const agentSummary = Object.entries(agentCounts)
|
|
301
|
-
.map(([a, c]) => `${a}:${c}`)
|
|
302
|
-
.join(' ')
|
|
303
|
-
|
|
304
|
-
out.done(`${tasks.length} tasks [${agentSummary}]`)
|
|
305
|
-
|
|
306
|
-
return { success: true, feature: description, featureId, tasks: tasksWithAgents }
|
|
307
|
-
} catch (error) {
|
|
308
|
-
out.fail(getErrorMessage(error))
|
|
309
|
-
return { success: false, error: getErrorMessage(error) }
|
|
310
|
-
}
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
/**
|
|
314
|
-
* /p:bug - Report and track bugs with auto-prioritization
|
|
315
|
-
*/
|
|
316
|
-
async bug(description: string, projectPath: string = process.cwd()): Promise<CommandResult> {
|
|
317
|
-
try {
|
|
318
|
-
const initResult = await this.ensureProjectInit(projectPath)
|
|
319
|
-
if (!initResult.success) return initResult
|
|
320
|
-
|
|
321
|
-
if (!description) {
|
|
322
|
-
out.fail('bug description required')
|
|
323
|
-
return { success: false, error: 'Description required' }
|
|
324
|
-
}
|
|
325
|
-
|
|
326
|
-
const projectId = await configManager.getProjectId(projectPath)
|
|
327
|
-
if (!projectId) {
|
|
328
|
-
out.failWithHint('NO_PROJECT_ID')
|
|
329
|
-
return { success: false, error: 'No project ID found' }
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
out.spin('tracking bug...')
|
|
333
|
-
|
|
334
|
-
const context = (await contextBuilder.build(projectPath, { description })) as ProjectContext
|
|
335
|
-
const severity = this._detectBugSeverity(description)
|
|
336
|
-
|
|
337
|
-
const agentResult = await this._assignAgentForTask(
|
|
338
|
-
`fix bug: ${description}`,
|
|
339
|
-
projectPath,
|
|
340
|
-
context
|
|
341
|
-
)
|
|
342
|
-
const agent = agentResult.agent?.name || 'generalist'
|
|
343
|
-
|
|
344
|
-
// Map severity to Priority type
|
|
345
|
-
const priorityMap: Record<string, Priority> = {
|
|
346
|
-
critical: 'critical',
|
|
347
|
-
high: 'high',
|
|
348
|
-
medium: 'medium',
|
|
349
|
-
low: 'low',
|
|
350
|
-
}
|
|
351
|
-
const priority = priorityMap[severity] || 'medium'
|
|
352
|
-
|
|
353
|
-
// Write-through: Add bug task (JSON ā MD ā Event)
|
|
354
|
-
await queueStorage.addTask(projectId, {
|
|
355
|
-
description: `š ${description}`,
|
|
356
|
-
priority,
|
|
357
|
-
type: 'bug' as TaskType,
|
|
358
|
-
section: 'active' as TaskSection,
|
|
359
|
-
agent,
|
|
360
|
-
})
|
|
361
|
-
|
|
362
|
-
await this.logToMemory(projectPath, 'bug_reported', {
|
|
363
|
-
bug: description,
|
|
364
|
-
severity,
|
|
365
|
-
priority,
|
|
366
|
-
agent,
|
|
367
|
-
timestamp: dateHelper.getTimestamp(),
|
|
368
|
-
})
|
|
369
|
-
|
|
370
|
-
out.done(`bug [${severity}] ā ${agent}`)
|
|
371
|
-
showNextSteps('bug')
|
|
372
|
-
|
|
373
|
-
return { success: true, bug: description, severity, agent }
|
|
374
|
-
} catch (error) {
|
|
375
|
-
out.fail(getErrorMessage(error))
|
|
376
|
-
return { success: false, error: getErrorMessage(error) }
|
|
377
|
-
}
|
|
378
|
-
}
|
|
379
|
-
|
|
380
|
-
/**
|
|
381
|
-
* /p:architect - Execute architect plan and generate code
|
|
382
|
-
*/
|
|
383
|
-
async architect(
|
|
384
|
-
action: string = 'execute',
|
|
385
|
-
projectPath: string = process.cwd()
|
|
386
|
-
): Promise<CommandResult> {
|
|
387
|
-
if (action !== 'execute') {
|
|
388
|
-
return {
|
|
389
|
-
success: false,
|
|
390
|
-
message: 'ā Invalid action. Use: /p:architect execute',
|
|
391
|
-
}
|
|
392
|
-
}
|
|
393
|
-
|
|
394
|
-
try {
|
|
395
|
-
const initResult = await this.ensureProjectInit(projectPath)
|
|
396
|
-
if (!initResult.success) return initResult
|
|
397
|
-
|
|
398
|
-
console.log('šļø Architect Mode - Code Generation\n')
|
|
399
|
-
|
|
400
|
-
const globalPath = await this.getGlobalProjectPath(projectPath)
|
|
401
|
-
const planPath = path.join(globalPath, 'planning', 'architect-session.md')
|
|
402
|
-
|
|
403
|
-
let planContent: string
|
|
404
|
-
try {
|
|
405
|
-
planContent = await fileHelper.readFile(planPath)
|
|
406
|
-
} catch (_error) {
|
|
407
|
-
// No plan file - expected for projects without architect mode
|
|
408
|
-
return {
|
|
409
|
-
success: false,
|
|
410
|
-
message:
|
|
411
|
-
'ā No architect plan found.\n\n' +
|
|
412
|
-
'Create a plan first:\n' +
|
|
413
|
-
' 1. Run /p:init in an empty directory\n' +
|
|
414
|
-
' 2. Answer the discovery questions\n' +
|
|
415
|
-
' 3. Plan will be auto-generated\n' +
|
|
416
|
-
' 4. Then run /p:architect execute',
|
|
417
|
-
}
|
|
418
|
-
}
|
|
419
|
-
|
|
420
|
-
if (!planContent || planContent.trim() === '') {
|
|
421
|
-
return {
|
|
422
|
-
success: false,
|
|
423
|
-
message: 'ā Architect plan is empty',
|
|
424
|
-
}
|
|
425
|
-
}
|
|
426
|
-
|
|
427
|
-
console.log('š Reading architect plan...\n')
|
|
428
|
-
|
|
429
|
-
const ideaMatch = planContent.match(/## Project Idea\n(.+)/s)
|
|
430
|
-
const stackMatch = planContent.match(/\*\*Stack:\*\*\n([\s\S]+?)\n\n/)
|
|
431
|
-
const stepsMatch = planContent.match(/\*\*Implementation Steps:\*\*\n([\s\S]+?)\n\n/)
|
|
432
|
-
|
|
433
|
-
const idea = ideaMatch ? ideaMatch[1].split('\n')[0].trim() : 'Unknown project'
|
|
434
|
-
const stack = stackMatch ? stackMatch[1] : 'Not specified'
|
|
435
|
-
const steps = stepsMatch ? stepsMatch[1] : 'Not specified'
|
|
436
|
-
|
|
437
|
-
console.log(`š Project: ${idea}`)
|
|
438
|
-
console.log(`\nš§ Stack:\n${stack}`)
|
|
439
|
-
console.log(`\nš Implementation Steps:\n${steps}`)
|
|
440
|
-
|
|
441
|
-
console.log(`\n${'='.repeat(60)}`)
|
|
442
|
-
console.log('š¤ READY TO GENERATE CODE')
|
|
443
|
-
console.log('='.repeat(60))
|
|
444
|
-
|
|
445
|
-
console.log(
|
|
446
|
-
'\nThe architect plan is ready. Claude will now:\n' +
|
|
447
|
-
' 1. Read the architectural plan\n' +
|
|
448
|
-
' 2. Use Context7 for official documentation\n' +
|
|
449
|
-
' 3. Generate project structure\n' +
|
|
450
|
-
' 4. Create starter files with boilerplate\n'
|
|
451
|
-
)
|
|
452
|
-
|
|
453
|
-
console.log('\nš” This command shows the plan.')
|
|
454
|
-
console.log(' For code generation, Claude Code will read this plan')
|
|
455
|
-
console.log(' and generate the structure automatically.\n')
|
|
456
|
-
|
|
457
|
-
await this.logToMemory(projectPath, 'architect_executed', {
|
|
458
|
-
timestamp: dateHelper.getTimestamp(),
|
|
459
|
-
idea,
|
|
460
|
-
})
|
|
461
|
-
|
|
462
|
-
return {
|
|
463
|
-
success: true,
|
|
464
|
-
plan: planContent,
|
|
465
|
-
idea,
|
|
466
|
-
}
|
|
467
|
-
} catch (error) {
|
|
468
|
-
console.error('ā Error:', getErrorMessage(error))
|
|
469
|
-
return { success: false, error: getErrorMessage(error) }
|
|
470
|
-
}
|
|
471
|
-
}
|
|
472
|
-
|
|
473
|
-
/**
|
|
474
|
-
* /p:idea - Transform ideas into architectures or quick captures
|
|
475
|
-
*/
|
|
476
|
-
async idea(description: string, projectPath: string = process.cwd()): Promise<CommandResult> {
|
|
477
|
-
try {
|
|
478
|
-
const initResult = await this.ensureProjectInit(projectPath)
|
|
479
|
-
if (!initResult.success) return initResult
|
|
480
|
-
|
|
481
|
-
if (!description) {
|
|
482
|
-
out.fail('idea description required')
|
|
483
|
-
return { success: false, error: 'Idea description required' }
|
|
484
|
-
}
|
|
485
|
-
|
|
486
|
-
const projectId = await configManager.getProjectId(projectPath)
|
|
487
|
-
if (!projectId) {
|
|
488
|
-
out.failWithHint('NO_PROJECT_ID')
|
|
489
|
-
return { success: false, error: 'No project ID found' }
|
|
490
|
-
}
|
|
491
|
-
|
|
492
|
-
// Determine if simple or complex idea
|
|
493
|
-
const wordCount = description.split(/\s+/).length
|
|
494
|
-
const isComplex =
|
|
495
|
-
wordCount > 20 || description.includes('with') || description.includes('that')
|
|
496
|
-
|
|
497
|
-
if (isComplex) {
|
|
498
|
-
// Complex idea ā Create architecture session
|
|
499
|
-
out.spin('analyzing idea...')
|
|
500
|
-
|
|
501
|
-
const globalPath = pathManager.getGlobalProjectPath(projectId)
|
|
502
|
-
const sessionPath = path.join(globalPath, 'planning', 'architect-session.md')
|
|
503
|
-
const sessionContent = `# Architect Session
|
|
504
|
-
|
|
505
|
-
## Idea
|
|
506
|
-
${description}
|
|
507
|
-
|
|
508
|
-
## Status
|
|
509
|
-
Initialized - awaiting architecture design
|
|
510
|
-
|
|
511
|
-
## Next Steps
|
|
512
|
-
1. Define tech stack
|
|
513
|
-
2. Create system design
|
|
514
|
-
3. Break down into features
|
|
515
|
-
4. Generate roadmap
|
|
516
|
-
|
|
517
|
-
Generated: ${new Date().toLocaleString()}
|
|
518
|
-
`
|
|
519
|
-
await toolRegistry.get('Write')!(sessionPath, sessionContent)
|
|
520
|
-
|
|
521
|
-
await this.logToMemory(projectPath, 'idea_architecture_started', {
|
|
522
|
-
idea: description,
|
|
523
|
-
timestamp: dateHelper.getTimestamp(),
|
|
524
|
-
})
|
|
525
|
-
|
|
526
|
-
out.done('architecture session created')
|
|
527
|
-
console.log('\nš” Use /p:architect execute to continue planning\n')
|
|
528
|
-
|
|
529
|
-
return { success: true, mode: 'architecture', idea: description }
|
|
530
|
-
} else {
|
|
531
|
-
// Simple idea ā Quick capture (JSON ā MD ā Event)
|
|
532
|
-
out.spin('capturing idea...')
|
|
533
|
-
|
|
534
|
-
await ideasStorage.addIdea(projectId, description)
|
|
535
|
-
|
|
536
|
-
await this.logToMemory(projectPath, 'idea_captured', {
|
|
537
|
-
idea: description,
|
|
538
|
-
timestamp: dateHelper.getTimestamp(),
|
|
539
|
-
})
|
|
540
|
-
|
|
541
|
-
out.done(`idea captured: ${description.slice(0, 40)}`)
|
|
542
|
-
showNextSteps('idea')
|
|
543
|
-
|
|
544
|
-
return { success: true, mode: 'capture', idea: description }
|
|
545
|
-
}
|
|
546
|
-
} catch (error) {
|
|
547
|
-
out.fail(getErrorMessage(error))
|
|
548
|
-
return { success: false, error: getErrorMessage(error) }
|
|
549
|
-
}
|
|
550
|
-
}
|
|
551
|
-
|
|
552
|
-
/**
|
|
553
|
-
* /p:spec - Create detailed specifications for complex features
|
|
554
|
-
*/
|
|
555
|
-
async spec(
|
|
556
|
-
featureName: string | null = null,
|
|
557
|
-
projectPath: string = process.cwd()
|
|
558
|
-
): Promise<CommandResult> {
|
|
559
|
-
try {
|
|
560
|
-
const initResult = await this.ensureProjectInit(projectPath)
|
|
561
|
-
if (!initResult.success) return initResult
|
|
562
|
-
|
|
563
|
-
const projectId = await configManager.getProjectId(projectPath)
|
|
564
|
-
if (!projectId) {
|
|
565
|
-
out.failWithHint('NO_PROJECT_ID')
|
|
566
|
-
return { success: false, error: 'No project ID found' }
|
|
567
|
-
}
|
|
568
|
-
|
|
569
|
-
if (!featureName) {
|
|
570
|
-
// List existing specs
|
|
571
|
-
out.spin('loading specs...')
|
|
572
|
-
|
|
573
|
-
const globalPath = pathManager.getGlobalProjectPath(projectId)
|
|
574
|
-
const specsPath = path.join(globalPath, 'planning', 'specs')
|
|
575
|
-
|
|
576
|
-
try {
|
|
577
|
-
const fs = await import('node:fs/promises')
|
|
578
|
-
const files = await fs.readdir(specsPath)
|
|
579
|
-
const specs = files.filter((f) => f.endsWith('.md') && f !== '.gitkeep')
|
|
580
|
-
|
|
581
|
-
if (specs.length === 0) {
|
|
582
|
-
out.warn('no specs yet')
|
|
583
|
-
console.log('\nš” Create one with /p:spec "feature name"\n')
|
|
584
|
-
return { success: true, specs: [] }
|
|
585
|
-
}
|
|
586
|
-
|
|
587
|
-
console.log('\nš SPECIFICATIONS\n')
|
|
588
|
-
console.log('ā'.repeat(50))
|
|
589
|
-
specs.forEach((s, i) => {
|
|
590
|
-
const name = s.replace('.md', '').replace(/-/g, ' ')
|
|
591
|
-
console.log(` ${i + 1}. ${name}`)
|
|
592
|
-
})
|
|
593
|
-
console.log(`${'ā'.repeat(50)}\n`)
|
|
594
|
-
|
|
595
|
-
return { success: true, specs }
|
|
596
|
-
} catch (_error) {
|
|
597
|
-
// No specs directory - expected for new projects
|
|
598
|
-
out.warn('no specs directory')
|
|
599
|
-
return { success: true, specs: [] }
|
|
600
|
-
}
|
|
601
|
-
}
|
|
602
|
-
|
|
603
|
-
// Create new spec
|
|
604
|
-
out.spin('creating spec...')
|
|
605
|
-
|
|
606
|
-
const globalPath = pathManager.getGlobalProjectPath(projectId)
|
|
607
|
-
const specsPath = path.join(globalPath, 'planning', 'specs')
|
|
608
|
-
await fileHelper.ensureDir(specsPath)
|
|
609
|
-
|
|
610
|
-
const slug = featureName.toLowerCase().replace(/\s+/g, '-')
|
|
611
|
-
const specFile = path.join(specsPath, `${slug}.md`)
|
|
612
|
-
|
|
613
|
-
const specContent = `# Specification: ${featureName}
|
|
614
|
-
|
|
615
|
-
## Overview
|
|
616
|
-
[Brief description of the feature]
|
|
617
|
-
|
|
618
|
-
## Requirements
|
|
619
|
-
- [ ] Requirement 1
|
|
620
|
-
- [ ] Requirement 2
|
|
621
|
-
- [ ] Requirement 3
|
|
622
|
-
|
|
623
|
-
## Design Decisions
|
|
624
|
-
| Decision | Rationale |
|
|
625
|
-
|----------|-----------|
|
|
626
|
-
| | |
|
|
627
|
-
|
|
628
|
-
## Tasks (20-30 min each)
|
|
629
|
-
1. [ ] Task 1 - [description]
|
|
630
|
-
2. [ ] Task 2 - [description]
|
|
631
|
-
3. [ ] Task 3 - [description]
|
|
632
|
-
|
|
633
|
-
## Acceptance Criteria
|
|
634
|
-
- [ ] Criterion 1
|
|
635
|
-
- [ ] Criterion 2
|
|
636
|
-
|
|
637
|
-
## Notes
|
|
638
|
-
[Additional notes and considerations]
|
|
639
|
-
|
|
640
|
-
---
|
|
641
|
-
Created: ${new Date().toLocaleString()}
|
|
642
|
-
Status: Draft
|
|
643
|
-
`
|
|
644
|
-
|
|
645
|
-
await toolRegistry.get('Write')!(specFile, specContent)
|
|
646
|
-
|
|
647
|
-
await this.logToMemory(projectPath, 'spec_created', {
|
|
648
|
-
feature: featureName,
|
|
649
|
-
timestamp: dateHelper.getTimestamp(),
|
|
650
|
-
})
|
|
651
|
-
|
|
652
|
-
out.done(`spec created: ${slug}.md`)
|
|
653
|
-
console.log(`\nš Edit: ~/.prjct-cli/projects/${projectId}/planning/specs/${slug}.md`)
|
|
654
|
-
console.log('š” When ready, use /p:feature to add tasks to queue\n')
|
|
655
|
-
|
|
656
|
-
return { success: true, feature: featureName, specPath: specFile }
|
|
657
|
-
} catch (error) {
|
|
658
|
-
out.fail(getErrorMessage(error))
|
|
659
|
-
return { success: false, error: getErrorMessage(error) }
|
|
660
|
-
}
|
|
661
|
-
}
|
|
662
|
-
}
|