prjct-cli 1.21.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 +244 -0
- package/README.md +41 -0
- package/bin/prjct +30 -13
- package/dist/bin/prjct.mjs +919 -35601
- 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/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 -502
- 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 -241
- 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 -316
- 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 -1404
- 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 -848
- 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,155 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* ProjectService - Project detection, validation, and path resolution
|
|
3
|
-
*
|
|
4
|
-
* Handles project initialization detection, author management, and directory analysis.
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import { ProjectError } from '../errors'
|
|
8
|
-
import * as authorDetector from '../infrastructure/author-detector'
|
|
9
|
-
import configManager from '../infrastructure/config-manager'
|
|
10
|
-
import pathManager from '../infrastructure/path-manager'
|
|
11
|
-
import type { Author, CommandResult } from '../types'
|
|
12
|
-
import { getErrorMessage, isNotFoundError } from '../types/fs'
|
|
13
|
-
import * as fileHelper from '../utils/file-helper'
|
|
14
|
-
import out from '../utils/output'
|
|
15
|
-
|
|
16
|
-
export class ProjectService {
|
|
17
|
-
private currentAuthor: Author | null = null
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Ensure project is initialized
|
|
21
|
-
*/
|
|
22
|
-
async ensureInit(projectPath: string): Promise<CommandResult> {
|
|
23
|
-
if (await configManager.isConfigured(projectPath)) {
|
|
24
|
-
return { success: true }
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
out.spin('initializing project...')
|
|
28
|
-
// Lazy import to avoid circular dependency
|
|
29
|
-
const { PlanningCommands } = await import('../commands/planning')
|
|
30
|
-
const planning = new PlanningCommands()
|
|
31
|
-
const initResult = await planning.init(null, projectPath)
|
|
32
|
-
|
|
33
|
-
if (!initResult.success) {
|
|
34
|
-
return initResult
|
|
35
|
-
}
|
|
36
|
-
return { success: true }
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* Get project ID for a path
|
|
41
|
-
*/
|
|
42
|
-
async getProjectId(projectPath: string): Promise<string> {
|
|
43
|
-
const projectId = await configManager.getProjectId(projectPath)
|
|
44
|
-
if (!projectId) {
|
|
45
|
-
throw ProjectError.notInitialized()
|
|
46
|
-
}
|
|
47
|
-
return projectId
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* Get global storage path for a project
|
|
52
|
-
*/
|
|
53
|
-
async getGlobalPath(projectPath: string): Promise<string> {
|
|
54
|
-
const projectId = await this.getProjectId(projectPath)
|
|
55
|
-
await pathManager.ensureProjectStructure(projectId)
|
|
56
|
-
return pathManager.getGlobalProjectPath(projectId)
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
/**
|
|
60
|
-
* Ensure author information is loaded
|
|
61
|
-
*/
|
|
62
|
-
async ensureAuthor(): Promise<Author> {
|
|
63
|
-
if (this.currentAuthor) return this.currentAuthor
|
|
64
|
-
|
|
65
|
-
const authorObj = await authorDetector.detect()
|
|
66
|
-
this.currentAuthor = {
|
|
67
|
-
name: authorObj.name ?? undefined,
|
|
68
|
-
email: authorObj.email ?? undefined,
|
|
69
|
-
github: authorObj.github ?? undefined,
|
|
70
|
-
}
|
|
71
|
-
return this.currentAuthor
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
/**
|
|
75
|
-
* Get current author
|
|
76
|
-
*/
|
|
77
|
-
getCurrentAuthor(): Author | null {
|
|
78
|
-
return this.currentAuthor
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
/**
|
|
82
|
-
* Clear cached author (useful for tests)
|
|
83
|
-
*/
|
|
84
|
-
clearAuthorCache(): void {
|
|
85
|
-
this.currentAuthor = null
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
/**
|
|
89
|
-
* Check if directory is empty (excluding common files)
|
|
90
|
-
*/
|
|
91
|
-
async isEmptyDirectory(projectPath: string): Promise<boolean> {
|
|
92
|
-
try {
|
|
93
|
-
const entries = await fileHelper.listFiles(projectPath)
|
|
94
|
-
const meaningfulFiles = entries.filter(
|
|
95
|
-
(name) =>
|
|
96
|
-
!name.startsWith('.') &&
|
|
97
|
-
name !== 'node_modules' &&
|
|
98
|
-
name !== 'package.json' &&
|
|
99
|
-
name !== 'package-lock.json' &&
|
|
100
|
-
name !== 'README.md'
|
|
101
|
-
)
|
|
102
|
-
return meaningfulFiles.length === 0
|
|
103
|
-
} catch (error) {
|
|
104
|
-
// Directory read error - treat as empty (expected for new dirs)
|
|
105
|
-
if (!isNotFoundError(error)) {
|
|
106
|
-
console.error(`Directory check error: ${getErrorMessage(error)}`)
|
|
107
|
-
}
|
|
108
|
-
return true
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
/**
|
|
113
|
-
* Check if directory has existing code
|
|
114
|
-
*/
|
|
115
|
-
async hasExistingCode(projectPath: string): Promise<boolean> {
|
|
116
|
-
try {
|
|
117
|
-
const codePatterns = [
|
|
118
|
-
'src',
|
|
119
|
-
'lib',
|
|
120
|
-
'app',
|
|
121
|
-
'components',
|
|
122
|
-
'pages',
|
|
123
|
-
'api',
|
|
124
|
-
'main.go',
|
|
125
|
-
'main.rs',
|
|
126
|
-
'main.py',
|
|
127
|
-
]
|
|
128
|
-
const entries = await fileHelper.listFiles(projectPath)
|
|
129
|
-
return entries.some((name) => codePatterns.includes(name))
|
|
130
|
-
} catch (error) {
|
|
131
|
-
// Directory read error - treat as no code (expected for new dirs)
|
|
132
|
-
if (!isNotFoundError(error)) {
|
|
133
|
-
console.error(`Code check error: ${getErrorMessage(error)}`)
|
|
134
|
-
}
|
|
135
|
-
return false
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
/**
|
|
140
|
-
* Check if project is configured
|
|
141
|
-
*/
|
|
142
|
-
async isConfigured(projectPath: string): Promise<boolean> {
|
|
143
|
-
return await configManager.isConfigured(projectPath)
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
/**
|
|
147
|
-
* Check if project needs migration
|
|
148
|
-
*/
|
|
149
|
-
async needsMigration(projectPath: string): Promise<boolean> {
|
|
150
|
-
return await configManager.needsMigration(projectPath)
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
export const projectService = new ProjectService()
|
|
155
|
-
export default projectService
|
|
@@ -1,287 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* SessionTracker - Lightweight session state tracking for multi-command workflows
|
|
3
|
-
*
|
|
4
|
-
* Tracks command sequences and file access across CLI invocations.
|
|
5
|
-
* Sessions auto-create on first command and expire after 30 min idle.
|
|
6
|
-
*
|
|
7
|
-
* Storage: ~/.prjct-cli/projects/{projectId}/storage/session.json
|
|
8
|
-
*
|
|
9
|
-
* @see PRJ-109
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
import fs from 'node:fs/promises'
|
|
13
|
-
import path from 'node:path'
|
|
14
|
-
import pathManager from '../infrastructure/path-manager'
|
|
15
|
-
import { isNotFoundError } from '../types/fs'
|
|
16
|
-
import { formatDuration, getTimestamp } from '../utils/date-helper'
|
|
17
|
-
|
|
18
|
-
// =============================================================================
|
|
19
|
-
// TYPES
|
|
20
|
-
// =============================================================================
|
|
21
|
-
|
|
22
|
-
export interface CommandRecord {
|
|
23
|
-
command: string
|
|
24
|
-
timestamp: string
|
|
25
|
-
durationMs: number
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
export interface FileRecord {
|
|
29
|
-
path: string
|
|
30
|
-
operation: 'read' | 'write'
|
|
31
|
-
timestamp: string
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
export interface SessionData {
|
|
35
|
-
id: string
|
|
36
|
-
projectId: string
|
|
37
|
-
status: 'active' | 'expired'
|
|
38
|
-
createdAt: string
|
|
39
|
-
lastActivity: string
|
|
40
|
-
commands: CommandRecord[]
|
|
41
|
-
files: FileRecord[]
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
export interface SessionFile {
|
|
45
|
-
current: SessionData | null
|
|
46
|
-
config: {
|
|
47
|
-
idleTimeoutMs: number
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
export interface SessionInfo {
|
|
52
|
-
active: boolean
|
|
53
|
-
id: string | null
|
|
54
|
-
duration: string | null
|
|
55
|
-
idleSince: string | null
|
|
56
|
-
idleMs: number
|
|
57
|
-
expiresIn: string | null
|
|
58
|
-
commandCount: number
|
|
59
|
-
commands: string[]
|
|
60
|
-
filesRead: number
|
|
61
|
-
filesWritten: number
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
// =============================================================================
|
|
65
|
-
// CONSTANTS
|
|
66
|
-
// =============================================================================
|
|
67
|
-
|
|
68
|
-
const SESSION_FILENAME = 'session.json'
|
|
69
|
-
const DEFAULT_IDLE_TIMEOUT_MS = 30 * 60 * 1000 // 30 minutes
|
|
70
|
-
const MAX_COMMAND_HISTORY = 50
|
|
71
|
-
const MAX_FILE_HISTORY = 200
|
|
72
|
-
|
|
73
|
-
// =============================================================================
|
|
74
|
-
// SESSION TRACKER
|
|
75
|
-
// =============================================================================
|
|
76
|
-
|
|
77
|
-
class SessionTracker {
|
|
78
|
-
private getPath(projectId: string): string {
|
|
79
|
-
return pathManager.getStoragePath(projectId, SESSION_FILENAME)
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
/**
|
|
83
|
-
* Read session file from disk
|
|
84
|
-
*/
|
|
85
|
-
private async read(projectId: string): Promise<SessionFile> {
|
|
86
|
-
const filePath = this.getPath(projectId)
|
|
87
|
-
try {
|
|
88
|
-
const content = await fs.readFile(filePath, 'utf-8')
|
|
89
|
-
return JSON.parse(content) as SessionFile
|
|
90
|
-
} catch (error) {
|
|
91
|
-
if (isNotFoundError(error) || error instanceof SyntaxError) {
|
|
92
|
-
return this.getDefault()
|
|
93
|
-
}
|
|
94
|
-
throw error
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
/**
|
|
99
|
-
* Write session file to disk
|
|
100
|
-
*/
|
|
101
|
-
private async write(projectId: string, data: SessionFile): Promise<void> {
|
|
102
|
-
const filePath = this.getPath(projectId)
|
|
103
|
-
await fs.mkdir(path.dirname(filePath), { recursive: true })
|
|
104
|
-
await fs.writeFile(filePath, JSON.stringify(data, null, 2), 'utf-8')
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
private getDefault(): SessionFile {
|
|
108
|
-
return {
|
|
109
|
-
current: null,
|
|
110
|
-
config: {
|
|
111
|
-
idleTimeoutMs: DEFAULT_IDLE_TIMEOUT_MS,
|
|
112
|
-
},
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
/**
|
|
117
|
-
* Check if a session has expired based on idle timeout
|
|
118
|
-
*/
|
|
119
|
-
private isExpired(session: SessionData, timeoutMs: number): boolean {
|
|
120
|
-
const lastActivity = new Date(session.lastActivity).getTime()
|
|
121
|
-
const now = Date.now()
|
|
122
|
-
return now - lastActivity > timeoutMs
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
/**
|
|
126
|
-
* Touch session — create new or resume existing.
|
|
127
|
-
* Called at the start of every CLI command.
|
|
128
|
-
* Returns the active session.
|
|
129
|
-
*/
|
|
130
|
-
async touch(projectId: string): Promise<SessionData> {
|
|
131
|
-
const file = await this.read(projectId)
|
|
132
|
-
const now = getTimestamp()
|
|
133
|
-
|
|
134
|
-
// If active session exists and not expired, resume it
|
|
135
|
-
if (file.current && !this.isExpired(file.current, file.config.idleTimeoutMs)) {
|
|
136
|
-
file.current.lastActivity = now
|
|
137
|
-
await this.write(projectId, file)
|
|
138
|
-
return file.current
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
// Create new session (old one expired or doesn't exist)
|
|
142
|
-
const session: SessionData = {
|
|
143
|
-
id: crypto.randomUUID(),
|
|
144
|
-
projectId,
|
|
145
|
-
status: 'active',
|
|
146
|
-
createdAt: now,
|
|
147
|
-
lastActivity: now,
|
|
148
|
-
commands: [],
|
|
149
|
-
files: [],
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
file.current = session
|
|
153
|
-
await this.write(projectId, file)
|
|
154
|
-
return session
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
/**
|
|
158
|
-
* Record a command execution in the current session
|
|
159
|
-
*/
|
|
160
|
-
async trackCommand(projectId: string, command: string, durationMs: number): Promise<void> {
|
|
161
|
-
const file = await this.read(projectId)
|
|
162
|
-
if (!file.current) return
|
|
163
|
-
|
|
164
|
-
const now = getTimestamp()
|
|
165
|
-
file.current.lastActivity = now
|
|
166
|
-
file.current.commands.push({
|
|
167
|
-
command,
|
|
168
|
-
timestamp: now,
|
|
169
|
-
durationMs,
|
|
170
|
-
})
|
|
171
|
-
|
|
172
|
-
// Trim old commands if over limit
|
|
173
|
-
if (file.current.commands.length > MAX_COMMAND_HISTORY) {
|
|
174
|
-
file.current.commands = file.current.commands.slice(-MAX_COMMAND_HISTORY)
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
await this.write(projectId, file)
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
/**
|
|
181
|
-
* Record a file access in the current session
|
|
182
|
-
*/
|
|
183
|
-
async trackFile(projectId: string, filePath: string, operation: 'read' | 'write'): Promise<void> {
|
|
184
|
-
const file = await this.read(projectId)
|
|
185
|
-
if (!file.current) return
|
|
186
|
-
|
|
187
|
-
const now = getTimestamp()
|
|
188
|
-
file.current.lastActivity = now
|
|
189
|
-
file.current.files.push({
|
|
190
|
-
path: filePath,
|
|
191
|
-
operation,
|
|
192
|
-
timestamp: now,
|
|
193
|
-
})
|
|
194
|
-
|
|
195
|
-
// Trim old file records if over limit
|
|
196
|
-
if (file.current.files.length > MAX_FILE_HISTORY) {
|
|
197
|
-
file.current.files = file.current.files.slice(-MAX_FILE_HISTORY)
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
await this.write(projectId, file)
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
/**
|
|
204
|
-
* Get session info for display (used by `prjct status`)
|
|
205
|
-
*/
|
|
206
|
-
async getInfo(projectId: string): Promise<SessionInfo> {
|
|
207
|
-
const file = await this.read(projectId)
|
|
208
|
-
|
|
209
|
-
if (!file.current || this.isExpired(file.current, file.config.idleTimeoutMs)) {
|
|
210
|
-
return {
|
|
211
|
-
active: false,
|
|
212
|
-
id: null,
|
|
213
|
-
duration: null,
|
|
214
|
-
idleSince: null,
|
|
215
|
-
idleMs: 0,
|
|
216
|
-
expiresIn: null,
|
|
217
|
-
commandCount: 0,
|
|
218
|
-
commands: [],
|
|
219
|
-
filesRead: 0,
|
|
220
|
-
filesWritten: 0,
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
const session = file.current
|
|
225
|
-
const now = Date.now()
|
|
226
|
-
const createdAt = new Date(session.createdAt).getTime()
|
|
227
|
-
const lastActivity = new Date(session.lastActivity).getTime()
|
|
228
|
-
const idleMs = now - lastActivity
|
|
229
|
-
const timeoutMs = file.config.idleTimeoutMs
|
|
230
|
-
const expiresInMs = Math.max(0, timeoutMs - idleMs)
|
|
231
|
-
|
|
232
|
-
const uniqueCommands = session.commands.map((c) => c.command)
|
|
233
|
-
const filesRead = new Set(
|
|
234
|
-
session.files.filter((f) => f.operation === 'read').map((f) => f.path)
|
|
235
|
-
).size
|
|
236
|
-
const filesWritten = new Set(
|
|
237
|
-
session.files.filter((f) => f.operation === 'write').map((f) => f.path)
|
|
238
|
-
).size
|
|
239
|
-
|
|
240
|
-
return {
|
|
241
|
-
active: true,
|
|
242
|
-
id: session.id,
|
|
243
|
-
duration: formatDuration(now - createdAt),
|
|
244
|
-
idleSince: session.lastActivity,
|
|
245
|
-
idleMs,
|
|
246
|
-
expiresIn: formatDuration(expiresInMs),
|
|
247
|
-
commandCount: session.commands.length,
|
|
248
|
-
commands: uniqueCommands,
|
|
249
|
-
filesRead,
|
|
250
|
-
filesWritten,
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
/**
|
|
255
|
-
* Expire the current session (cleanup)
|
|
256
|
-
*/
|
|
257
|
-
async expire(projectId: string): Promise<void> {
|
|
258
|
-
const file = await this.read(projectId)
|
|
259
|
-
if (file.current) {
|
|
260
|
-
file.current.status = 'expired'
|
|
261
|
-
file.current = null
|
|
262
|
-
await this.write(projectId, file)
|
|
263
|
-
}
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
/**
|
|
267
|
-
* Check and expire stale session if needed.
|
|
268
|
-
* Called on startup to clean up leftover sessions.
|
|
269
|
-
* Returns true if a session was expired.
|
|
270
|
-
*/
|
|
271
|
-
async expireIfStale(projectId: string): Promise<boolean> {
|
|
272
|
-
const file = await this.read(projectId)
|
|
273
|
-
if (file.current && this.isExpired(file.current, file.config.idleTimeoutMs)) {
|
|
274
|
-
file.current = null
|
|
275
|
-
await this.write(projectId, file)
|
|
276
|
-
return true
|
|
277
|
-
}
|
|
278
|
-
return false
|
|
279
|
-
}
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
// =============================================================================
|
|
283
|
-
// EXPORTS
|
|
284
|
-
// =============================================================================
|
|
285
|
-
|
|
286
|
-
export const sessionTracker = new SessionTracker()
|
|
287
|
-
export default sessionTracker
|