prjct-cli 0.15.0 → 0.17.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.
Files changed (59) hide show
  1. package/CHANGELOG.md +51 -0
  2. package/bin/dev.js +0 -1
  3. package/bin/serve.js +19 -20
  4. package/core/agentic/agent-router.ts +79 -14
  5. package/core/agentic/command-executor/command-executor.ts +2 -74
  6. package/core/agentic/services.ts +0 -48
  7. package/core/agentic/template-loader.ts +35 -1
  8. package/core/commands/base.ts +96 -77
  9. package/core/commands/planning.ts +13 -2
  10. package/core/commands/setup.ts +3 -85
  11. package/core/errors.ts +209 -0
  12. package/core/infrastructure/config-manager.ts +22 -5
  13. package/core/infrastructure/setup.ts +5 -50
  14. package/core/storage/storage-manager.ts +42 -6
  15. package/core/utils/logger.ts +19 -12
  16. package/package.json +2 -4
  17. package/templates/agentic/subagent-generation.md +109 -0
  18. package/templates/commands/setup.md +18 -3
  19. package/templates/commands/sync.md +74 -13
  20. package/templates/mcp-config.json +20 -1
  21. package/templates/subagents/domain/backend.md +105 -0
  22. package/templates/subagents/domain/database.md +118 -0
  23. package/templates/subagents/domain/devops.md +148 -0
  24. package/templates/subagents/domain/frontend.md +99 -0
  25. package/templates/subagents/domain/testing.md +169 -0
  26. package/templates/subagents/workflow/prjct-planner.md +158 -0
  27. package/templates/subagents/workflow/prjct-shipper.md +179 -0
  28. package/templates/subagents/workflow/prjct-workflow.md +98 -0
  29. package/bin/generate-views.js +0 -209
  30. package/bin/migrate-to-json.js +0 -742
  31. package/core/agentic/context-filter.ts +0 -365
  32. package/core/agentic/parallel-tools.ts +0 -165
  33. package/core/agentic/response-templates.ts +0 -164
  34. package/core/agentic/semantic-compression.ts +0 -273
  35. package/core/agentic/think-blocks.ts +0 -202
  36. package/core/agentic/validation-rules.ts +0 -313
  37. package/core/domain/agent-matcher.ts +0 -130
  38. package/core/domain/agent-validator.ts +0 -250
  39. package/core/domain/architect-session.ts +0 -315
  40. package/core/domain/product-standards.ts +0 -106
  41. package/core/domain/smart-cache.ts +0 -167
  42. package/core/domain/task-analyzer.ts +0 -296
  43. package/core/infrastructure/legacy-installer-detector/cleanup.ts +0 -216
  44. package/core/infrastructure/legacy-installer-detector/detection.ts +0 -95
  45. package/core/infrastructure/legacy-installer-detector/index.ts +0 -171
  46. package/core/infrastructure/legacy-installer-detector/migration.ts +0 -87
  47. package/core/infrastructure/legacy-installer-detector/types.ts +0 -42
  48. package/core/infrastructure/legacy-installer-detector.ts +0 -7
  49. package/core/infrastructure/migrator/file-operations.ts +0 -125
  50. package/core/infrastructure/migrator/index.ts +0 -288
  51. package/core/infrastructure/migrator/project-scanner.ts +0 -90
  52. package/core/infrastructure/migrator/reports.ts +0 -117
  53. package/core/infrastructure/migrator/types.ts +0 -124
  54. package/core/infrastructure/migrator/validation.ts +0 -94
  55. package/core/infrastructure/migrator/version-migration.ts +0 -117
  56. package/core/infrastructure/migrator.ts +0 -10
  57. package/core/infrastructure/uuid-migration.ts +0 -750
  58. package/templates/commands/migrate-all.md +0 -96
  59. package/templates/commands/migrate.md +0 -140
@@ -1,171 +0,0 @@
1
- /**
2
- * Legacy Installer Detector
3
- *
4
- * Detects and cleans up legacy curl-based installations from ~/.prjct-cli/
5
- *
6
- * @version 0.8.8
7
- */
8
-
9
- import {
10
- legacyInstallDir,
11
- npmGlobalProjectsDir,
12
- isWindows,
13
- hasLegacyInstallation,
14
- getNpmGlobalPath,
15
- hasNpmInstallation,
16
- getLegacyVersion,
17
- needsCleanup,
18
- } from './detection'
19
-
20
- import { migrateProjectsData } from './migration'
21
-
22
- import {
23
- cleanupLegacyInstallation,
24
- cleanupLegacyPATH,
25
- cleanupLegacySymlinks,
26
- getShellConfigFiles,
27
- } from './cleanup'
28
-
29
- import type { CleanupReport, CleanupOptions } from './types'
30
- import { CYAN, GREEN, YELLOW, RED, DIM, NC } from './types'
31
-
32
- class LegacyInstallerDetector {
33
- legacyInstallDir = legacyInstallDir
34
- npmGlobalProjectsDir = npmGlobalProjectsDir
35
- isWindows = isWindows
36
-
37
- hasLegacyInstallation = hasLegacyInstallation
38
- getNpmGlobalPath = getNpmGlobalPath
39
- hasNpmInstallation = hasNpmInstallation
40
- getLegacyVersion = getLegacyVersion
41
- needsCleanup = needsCleanup
42
- migrateProjectsData = migrateProjectsData
43
- cleanupLegacyInstallation = cleanupLegacyInstallation
44
- cleanupLegacyPATH = cleanupLegacyPATH
45
- cleanupLegacySymlinks = cleanupLegacySymlinks
46
- getShellConfigFiles = getShellConfigFiles
47
-
48
- /**
49
- * Perform complete legacy cleanup
50
- */
51
- async performCleanup(options: CleanupOptions = {}): Promise<CleanupReport> {
52
- const { verbose = true } = options
53
-
54
- const report: CleanupReport = {
55
- success: false,
56
- legacyVersion: null,
57
- hasNpm: false,
58
- steps: {
59
- projectsMigrated: 0,
60
- installationCleaned: false,
61
- pathCleaned: false,
62
- symlinksCleaned: false,
63
- },
64
- messages: [],
65
- }
66
-
67
- try {
68
- const hasLegacy = await hasLegacyInstallation()
69
-
70
- if (!hasLegacy) {
71
- report.success = true
72
- report.messages.push('No legacy installation found')
73
- return report
74
- }
75
-
76
- report.legacyVersion = await getLegacyVersion()
77
- report.hasNpm = await hasNpmInstallation()
78
-
79
- if (verbose) {
80
- console.log('')
81
- console.log(`${YELLOW}----------------------------------------${NC}`)
82
- console.log(`${YELLOW}Legacy curl installation detected${NC}`)
83
- console.log(`${YELLOW}----------------------------------------${NC}`)
84
- console.log('')
85
- console.log(` ${DIM}Version: ${report.legacyVersion || 'unknown'}${NC}`)
86
- console.log(` ${DIM}Location: ~/.prjct-cli/${NC}`)
87
- console.log('')
88
-
89
- if (!report.hasNpm) {
90
- console.log(`${RED}npm global installation not found${NC}`)
91
- console.log('')
92
- console.log(`${CYAN}Install prjct-cli via npm first:${NC}`)
93
- console.log(` ${GREEN}npm install -g prjct-cli${NC}`)
94
- console.log('')
95
- return report
96
- }
97
-
98
- console.log(`${CYAN}Migrating to npm installation...${NC}`)
99
- console.log('')
100
- }
101
-
102
- // Step 1: Migrate projects data
103
- if (verbose) console.log(` ${DIM}Migrating projects data...${NC}`)
104
- const projectsMigration = await migrateProjectsData()
105
- report.steps.projectsMigrated = projectsMigration.projectsMigrated
106
- report.messages.push(projectsMigration.message)
107
- if (verbose) {
108
- const icon = projectsMigration.success ? `${GREEN}✓${NC}` : `${RED}✗${NC}`
109
- console.log(` ${icon} ${projectsMigration.message}`)
110
- }
111
-
112
- // Step 2: Clean legacy installation
113
- if (verbose) console.log(` ${DIM}Removing legacy files...${NC}`)
114
- const installCleanup = await cleanupLegacyInstallation()
115
- report.steps.installationCleaned = installCleanup.success
116
- report.messages.push(installCleanup.message)
117
- if (verbose) {
118
- const icon = installCleanup.success ? `${GREEN}✓${NC}` : `${RED}✗${NC}`
119
- console.log(` ${icon} ${installCleanup.message}`)
120
- }
121
-
122
- // Step 3: Clean PATH entries
123
- if (verbose) console.log(` ${DIM}Cleaning shell PATH...${NC}`)
124
- const pathCleanup = await cleanupLegacyPATH()
125
- report.steps.pathCleaned = pathCleanup.success
126
- report.messages.push(pathCleanup.message)
127
- if (verbose) {
128
- const icon = pathCleanup.success ? `${GREEN}✓${NC}` : `${RED}✗${NC}`
129
- console.log(` ${icon} ${pathCleanup.message}`)
130
- }
131
-
132
- // Step 4: Clean symlinks
133
- if (verbose) console.log(` ${DIM}Cleaning symlinks...${NC}`)
134
- const symlinkCleanup = await cleanupLegacySymlinks()
135
- report.steps.symlinksCleaned = symlinkCleanup.success
136
- report.messages.push(symlinkCleanup.message)
137
- if (verbose) {
138
- const icon = symlinkCleanup.success ? `${GREEN}✓${NC}` : `${RED}✗${NC}`
139
- console.log(` ${icon} ${symlinkCleanup.message}`)
140
- }
141
-
142
- if (verbose) {
143
- console.log('')
144
- console.log(`${GREEN}Migration complete!${NC}`)
145
- console.log('')
146
- console.log(`${DIM}Next steps:${NC}`)
147
- if (pathCleanup.filesModified && pathCleanup.filesModified > 0) {
148
- console.log(` ${CYAN}1. Reload your shell:${NC}`)
149
- console.log(` source ~/.zshrc ${DIM}(or ~/.bashrc)${NC}`)
150
- console.log('')
151
- }
152
- const stepNum = pathCleanup.filesModified && pathCleanup.filesModified > 0 ? '2' : '1'
153
- console.log(` ${CYAN}${stepNum}. Verify installation:${NC}`)
154
- console.log(` which prjct ${DIM}(should show npm path)${NC}`)
155
- console.log(` prjct --version`)
156
- console.log('')
157
- console.log(`${YELLOW}----------------------------------------${NC}`)
158
- console.log('')
159
- }
160
-
161
- report.success = true
162
- return report
163
- } catch (error) {
164
- report.messages.push(`Cleanup failed: ${(error as Error).message}`)
165
- return report
166
- }
167
- }
168
- }
169
-
170
- const legacyInstallerDetector = new LegacyInstallerDetector()
171
- export default legacyInstallerDetector
@@ -1,87 +0,0 @@
1
- /**
2
- * Migration - Project Data Migration
3
- */
4
-
5
- import fs from 'fs/promises'
6
- import path from 'path'
7
- import { legacyInstallDir, npmGlobalProjectsDir } from './detection'
8
- import type { MigrationResult } from './types'
9
-
10
- /**
11
- * Copy directory recursively
12
- */
13
- async function copyDirectory(source: string, destination: string): Promise<void> {
14
- await fs.mkdir(destination, { recursive: true })
15
-
16
- const entries = await fs.readdir(source, { withFileTypes: true })
17
-
18
- for (const entry of entries) {
19
- const sourcePath = path.join(source, entry.name)
20
- const destPath = path.join(destination, entry.name)
21
-
22
- if (entry.isDirectory()) {
23
- await copyDirectory(sourcePath, destPath)
24
- } else {
25
- await fs.copyFile(sourcePath, destPath)
26
- }
27
- }
28
- }
29
-
30
- /**
31
- * Migrate projects data from legacy location to npm location
32
- */
33
- export async function migrateProjectsData(): Promise<MigrationResult> {
34
- const result: MigrationResult = {
35
- success: false,
36
- projectsMigrated: 0,
37
- message: '',
38
- }
39
-
40
- try {
41
- const legacyProjectsDir = path.join(legacyInstallDir, 'projects')
42
-
43
- // Check if legacy projects directory exists
44
- try {
45
- await fs.access(legacyProjectsDir)
46
- } catch {
47
- result.success = true
48
- result.message = 'No projects data to migrate'
49
- return result
50
- }
51
-
52
- // Ensure npm global projects directory exists
53
- await fs.mkdir(npmGlobalProjectsDir, { recursive: true })
54
-
55
- // Read all project directories
56
- const projectDirs = await fs.readdir(legacyProjectsDir, { withFileTypes: true })
57
-
58
- for (const entry of projectDirs) {
59
- if (!entry.isDirectory()) continue
60
-
61
- const legacyProjectPath = path.join(legacyProjectsDir, entry.name)
62
- const npmProjectPath = path.join(npmGlobalProjectsDir, entry.name)
63
-
64
- // Check if project already exists in npm location
65
- try {
66
- await fs.access(npmProjectPath)
67
- // Already exists, skip
68
- continue
69
- } catch {
70
- // Doesn't exist, copy it
71
- await copyDirectory(legacyProjectPath, npmProjectPath)
72
- result.projectsMigrated++
73
- }
74
- }
75
-
76
- result.success = true
77
- result.message =
78
- result.projectsMigrated > 0
79
- ? `Migrated ${result.projectsMigrated} project(s) to npm global location`
80
- : 'All projects already in npm location'
81
-
82
- return result
83
- } catch (error) {
84
- result.message = `Migration failed: ${(error as Error).message}`
85
- return result
86
- }
87
- }
@@ -1,42 +0,0 @@
1
- /**
2
- * Legacy Installer Detector Types
3
- */
4
-
5
- // Colors
6
- export const CYAN = '\x1b[36m'
7
- export const GREEN = '\x1b[32m'
8
- export const YELLOW = '\x1b[33m'
9
- export const RED = '\x1b[31m'
10
- export const DIM = '\x1b[2m'
11
- export const NC = '\x1b[0m'
12
-
13
- export interface CleanupSteps {
14
- projectsMigrated: number
15
- installationCleaned: boolean
16
- pathCleaned: boolean
17
- symlinksCleaned: boolean
18
- }
19
-
20
- export interface CleanupReport {
21
- success: boolean
22
- legacyVersion: string | null
23
- hasNpm: boolean
24
- steps: CleanupSteps
25
- messages: string[]
26
- }
27
-
28
- export interface MigrationResult {
29
- success: boolean
30
- projectsMigrated: number
31
- message: string
32
- }
33
-
34
- export interface CleanupResult {
35
- success: boolean
36
- message: string
37
- filesModified?: number
38
- }
39
-
40
- export interface CleanupOptions {
41
- verbose?: boolean
42
- }
@@ -1,7 +0,0 @@
1
- /**
2
- * Legacy Installer Detector
3
- * Re-exports from legacy-installer-detector/index.ts for backwards compatibility.
4
- */
5
-
6
- import legacyInstallerDetector from './legacy-installer-detector/index'
7
- export default legacyInstallerDetector
@@ -1,125 +0,0 @@
1
- /**
2
- * File Operations
3
- * Handles file copying and mapping for migrations.
4
- */
5
-
6
- import fs from 'fs/promises'
7
- import path from 'path'
8
- import type { FileMapping, MigrationStats, LayerCounts } from './types'
9
-
10
- /**
11
- * Copy a directory recursively
12
- */
13
- export async function copyDirectory(source: string, destination: string): Promise<number> {
14
- let fileCount = 0
15
-
16
- await fs.mkdir(destination, { recursive: true })
17
-
18
- const entries = await fs.readdir(source, { withFileTypes: true })
19
-
20
- for (const entry of entries) {
21
- const sourcePath = path.join(source, entry.name)
22
- const destPath = path.join(destination, entry.name)
23
-
24
- if (entry.isDirectory()) {
25
- fileCount += await copyDirectory(sourcePath, destPath)
26
- } else {
27
- await fs.copyFile(sourcePath, destPath)
28
- fileCount++
29
- }
30
- }
31
-
32
- return fileCount
33
- }
34
-
35
- /**
36
- * Map legacy flat structure to new layered structure
37
- */
38
- export function mapLegacyFile(filename: string): FileMapping {
39
- if (filename === 'now.md' || filename === 'next.md' || filename === 'context.md') {
40
- return { layer: 'core', filename }
41
- }
42
-
43
- if (filename === 'shipped.md' || filename === 'metrics.md') {
44
- return { layer: 'progress', filename }
45
- }
46
-
47
- if (filename === 'ideas.md' || filename === 'roadmap.md') {
48
- return { layer: 'planning', filename }
49
- }
50
-
51
- if (
52
- filename === 'memory.jsonl' ||
53
- filename === 'context.jsonl' ||
54
- filename === 'decisions.jsonl'
55
- ) {
56
- return { layer: 'memory', filename }
57
- }
58
-
59
- if (filename === 'repo-summary.md') {
60
- return { layer: 'analysis', filename }
61
- }
62
-
63
- return { layer: '.', filename }
64
- }
65
-
66
- /**
67
- * Migrate files from legacy structure to new layered structure
68
- */
69
- export async function migrateFiles(legacyPath: string, globalPath: string): Promise<MigrationStats> {
70
- let fileCount = 0
71
- const layerCounts: LayerCounts = {
72
- core: 0,
73
- progress: 0,
74
- planning: 0,
75
- analysis: 0,
76
- memory: 0,
77
- other: 0,
78
- }
79
-
80
- const validLayers = ['core', 'progress', 'planning', 'analysis', 'memory', 'sessions']
81
- const entries = await fs.readdir(legacyPath, { withFileTypes: true })
82
-
83
- for (const entry of entries) {
84
- const sourcePath = path.join(legacyPath, entry.name)
85
-
86
- if (entry.name === 'prjct.config.json' || entry.name.endsWith('.old')) {
87
- continue
88
- }
89
-
90
- if (entry.isDirectory()) {
91
- if (validLayers.includes(entry.name)) {
92
- const destPath = path.join(globalPath, entry.name)
93
- const count = await copyDirectory(sourcePath, destPath)
94
- fileCount += count
95
- if (Object.prototype.hasOwnProperty.call(layerCounts, entry.name)) {
96
- layerCounts[entry.name as keyof LayerCounts] += count
97
- } else {
98
- layerCounts.other += count
99
- }
100
- } else {
101
- const destPath = path.join(globalPath, 'planning', entry.name)
102
- const count = await copyDirectory(sourcePath, destPath)
103
- fileCount += count
104
- layerCounts.planning += count
105
- }
106
- } else {
107
- const mapping = mapLegacyFile(entry.name)
108
- const destPath = path.join(globalPath, mapping.layer, mapping.filename)
109
-
110
- await fs.mkdir(path.dirname(destPath), { recursive: true })
111
-
112
- await fs.copyFile(sourcePath, destPath)
113
- fileCount++
114
-
115
- if (mapping.layer === '.') {
116
- layerCounts.other++
117
- } else {
118
- layerCounts[mapping.layer as keyof LayerCounts] =
119
- (layerCounts[mapping.layer as keyof LayerCounts] || 0) + 1
120
- }
121
- }
122
- }
123
-
124
- return { fileCount, layerCounts }
125
- }