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,273 +0,0 @@
1
- /**
2
- * Semantic Compression
3
- * Compresses context while preserving meaning
4
- *
5
- * @module agentic/semantic-compression
6
- * @version 1.0.0
7
- */
8
-
9
- interface CompressionResult {
10
- summary: string
11
- originalLength: number
12
- compressedLength: number
13
- ratio: number
14
- key: string
15
- }
16
-
17
- interface CompressionMetrics {
18
- totalOriginal: number
19
- totalCompressed: number
20
- overallRatio: number
21
- compressions: number
22
- }
23
-
24
- class SemanticCompression {
25
- private metrics: CompressionMetrics
26
-
27
- constructor() {
28
- this.metrics = {
29
- totalOriginal: 0,
30
- totalCompressed: 0,
31
- overallRatio: 1,
32
- compressions: 0,
33
- }
34
- }
35
-
36
- /**
37
- * Compress content while preserving semantic meaning
38
- */
39
- compress(content: string, key: string): CompressionResult {
40
- if (!content || !content.trim()) {
41
- return {
42
- summary: 'Empty',
43
- originalLength: 0,
44
- compressedLength: 0,
45
- ratio: 1,
46
- key,
47
- }
48
- }
49
-
50
- const originalLength = content.length
51
- let summary: string
52
-
53
- // Apply key-specific compression strategies
54
- switch (key) {
55
- case 'now':
56
- summary = this.compressNow(content)
57
- break
58
- case 'next':
59
- summary = this.compressNext(content)
60
- break
61
- case 'shipped':
62
- summary = this.compressShipped(content)
63
- break
64
- case 'analysis':
65
- summary = this.compressAnalysis(content)
66
- break
67
- case 'roadmap':
68
- summary = this.compressRoadmap(content)
69
- break
70
- case 'codePatterns':
71
- summary = this.compressCodePatterns(content)
72
- break
73
- default:
74
- summary = this.compressGeneric(content)
75
- }
76
-
77
- const compressedLength = summary.length
78
- const ratio = originalLength > 0 ? compressedLength / originalLength : 1
79
-
80
- // Update metrics
81
- this.metrics.totalOriginal += originalLength
82
- this.metrics.totalCompressed += compressedLength
83
- this.metrics.compressions++
84
- this.metrics.overallRatio =
85
- this.metrics.totalOriginal > 0 ? this.metrics.totalCompressed / this.metrics.totalOriginal : 1
86
-
87
- return {
88
- summary,
89
- originalLength,
90
- compressedLength,
91
- ratio,
92
- key,
93
- }
94
- }
95
-
96
- /**
97
- * Compress now.md content
98
- */
99
- private compressNow(content: string): string {
100
- // Extract task description
101
- const taskMatch = content.match(/task:\s*["']?([^"'\n]+)["']?/i) || content.match(/#+\s*(.+)/m)
102
- const task = taskMatch ? taskMatch[1].trim() : 'Unknown task'
103
-
104
- // Extract started time
105
- const startedMatch = content.match(/started:\s*(.+)/i)
106
- const started = startedMatch ? startedMatch[1].trim() : ''
107
-
108
- // Extract agent if present
109
- const agentMatch = content.match(/agent:\s*(.+)/i)
110
- const agent = agentMatch ? agentMatch[1].trim() : ''
111
-
112
- let summary = `Task: ${task}`
113
- if (started) summary += ` | Started: ${started}`
114
- if (agent) summary += ` | Agent: ${agent}`
115
-
116
- return summary
117
- }
118
-
119
- /**
120
- * Compress next.md content
121
- */
122
- private compressNext(content: string): string {
123
- // Count tasks
124
- const pending = (content.match(/- \[ \]/g) || []).length
125
- const completed = (content.match(/- \[x\]/gi) || []).length
126
- const total = pending + completed
127
-
128
- // Get first few pending tasks
129
- const taskLines = content.match(/- \[ \] .+/g) || []
130
- const topTasks = taskLines.slice(0, 3).map((t) => t.replace('- [ ] ', '').trim())
131
-
132
- let summary = `Queue: ${pending} pending, ${completed} done (${total} total)`
133
- if (topTasks.length > 0) {
134
- summary += ` | Next: ${topTasks.join(', ')}`
135
- }
136
-
137
- return summary
138
- }
139
-
140
- /**
141
- * Compress shipped.md content
142
- */
143
- private compressShipped(content: string): string {
144
- // Count shipped items
145
- const shipped = (content.match(/^##\s+/gm) || []).length
146
- const lines = content.split('\n')
147
-
148
- // Get most recent ship
149
- let recentShip = ''
150
- for (const line of lines) {
151
- if (line.startsWith('## ')) {
152
- recentShip = line.replace('## ', '').trim()
153
- break
154
- }
155
- }
156
-
157
- let summary = `Shipped: ${shipped} items`
158
- if (recentShip) summary += ` | Recent: ${recentShip.substring(0, 50)}`
159
-
160
- return summary
161
- }
162
-
163
- /**
164
- * Compress analysis content
165
- */
166
- private compressAnalysis(content: string): string {
167
- // Extract stack
168
- const stackMatch =
169
- content.match(/stack[:\s]+([^\n]+)/i) ||
170
- content.match(/technology[:\s]+([^\n]+)/i) ||
171
- content.match(/framework[:\s]+([^\n]+)/i)
172
- const stack = stackMatch ? stackMatch[1].trim() : 'Unknown'
173
-
174
- // Extract file count if present
175
- const filesMatch = content.match(/(\d+)\s*files/i)
176
- const files = filesMatch ? filesMatch[1] : ''
177
-
178
- // Extract language
179
- const langMatch = content.match(/language[:\s]+([^\n]+)/i) || content.match(/primary[:\s]+([^\n]+)/i)
180
- const language = langMatch ? langMatch[1].trim() : ''
181
-
182
- let summary = `Stack: ${stack}`
183
- if (language) summary += ` | Language: ${language}`
184
- if (files) summary += ` | Files: ${files}`
185
-
186
- return summary
187
- }
188
-
189
- /**
190
- * Compress roadmap content
191
- */
192
- private compressRoadmap(content: string): string {
193
- // Count features
194
- const features = (content.match(/^##\s+/gm) || []).length
195
-
196
- // Get feature names
197
- const featureNames: string[] = []
198
- const matches = content.match(/^##\s+(.+)/gm) || []
199
- matches.slice(0, 3).forEach((m) => {
200
- featureNames.push(m.replace(/^##\s+/, '').trim())
201
- })
202
-
203
- let summary = `Roadmap: ${features} features`
204
- if (featureNames.length > 0) {
205
- summary += ` | Top: ${featureNames.join(', ')}`
206
- }
207
-
208
- return summary
209
- }
210
-
211
- /**
212
- * Compress code patterns content
213
- */
214
- private compressCodePatterns(content: string): string {
215
- // Extract conventions section
216
- const conventionsMatch = content.match(/## Conventions[\s\S]*?(?=##|$)/i)
217
- let conventions = ''
218
- if (conventionsMatch) {
219
- const lines = conventionsMatch[0]
220
- .split('\n')
221
- .filter((l) => l.includes(':') || l.startsWith('-'))
222
- .slice(0, 3)
223
- conventions = lines.join(' | ')
224
- }
225
-
226
- // Check for anti-patterns
227
- const hasAntiPatterns = content.toLowerCase().includes('anti-pattern')
228
-
229
- let summary = 'Code patterns loaded'
230
- if (conventions) summary += ` | ${conventions.substring(0, 100)}`
231
- if (hasAntiPatterns) summary += ' | Has anti-patterns'
232
-
233
- return summary
234
- }
235
-
236
- /**
237
- * Generic compression
238
- */
239
- private compressGeneric(content: string): string {
240
- // Take first meaningful lines
241
- const lines = content.split('\n').filter((l) => l.trim() && !l.startsWith('#'))
242
- const preview = lines.slice(0, 2).join(' | ')
243
-
244
- if (preview.length > 150) {
245
- return preview.substring(0, 150) + '...'
246
- }
247
-
248
- return preview || 'Content available'
249
- }
250
-
251
- /**
252
- * Get compression metrics
253
- */
254
- getMetrics(): CompressionMetrics {
255
- return { ...this.metrics }
256
- }
257
-
258
- /**
259
- * Reset metrics
260
- */
261
- resetMetrics(): void {
262
- this.metrics = {
263
- totalOriginal: 0,
264
- totalCompressed: 0,
265
- overallRatio: 1,
266
- compressions: 0,
267
- }
268
- }
269
- }
270
-
271
- const semanticCompression = new SemanticCompression()
272
- export default semanticCompression
273
- export { SemanticCompression }
@@ -1,202 +0,0 @@
1
- /**
2
- * Think Blocks
3
- * Dynamic reasoning blocks for complex decisions
4
- *
5
- * @module agentic/think-blocks
6
- * @version 1.0.0
7
- */
8
-
9
- interface Context {
10
- params: Record<string, unknown>
11
- [key: string]: unknown
12
- }
13
-
14
- interface State {
15
- now?: string | null
16
- analysis?: string | null
17
- codePatterns?: string | null
18
- [key: string]: unknown
19
- }
20
-
21
- interface ThinkTrigger {
22
- type: string
23
- reason: string
24
- priority: 'high' | 'medium' | 'low'
25
- }
26
-
27
- interface ThinkBlock {
28
- trigger: ThinkTrigger
29
- commandName: string
30
- conclusions: string[]
31
- plan: string[]
32
- confidence: number
33
- generatedAt: string
34
- }
35
-
36
- /**
37
- * Detect if a think block is needed
38
- */
39
- function detectTrigger(commandName: string, context: Context, state: State): ThinkTrigger | null {
40
- // High-priority triggers (always think)
41
- const highPriorityCommands = ['ship', 'cleanup', 'migrate']
42
- if (highPriorityCommands.includes(commandName)) {
43
- return {
44
- type: 'critical_command',
45
- reason: `${commandName} is a critical command requiring careful planning`,
46
- priority: 'high',
47
- }
48
- }
49
-
50
- // Check for complex task
51
- const taskDescription = (context.params.task as string) || (context.params.description as string) || ''
52
- if (taskDescription.length > 100) {
53
- return {
54
- type: 'complex_task',
55
- reason: 'Task description is complex, requiring analysis',
56
- priority: 'medium',
57
- }
58
- }
59
-
60
- // Check for existing task (potential conflict)
61
- if (state.now && !state.now.includes('No current task') && commandName === 'now') {
62
- return {
63
- type: 'task_conflict',
64
- reason: 'Already has active task, need to decide how to handle',
65
- priority: 'medium',
66
- }
67
- }
68
-
69
- // Check if analysis exists (context-aware)
70
- if (!state.analysis && ['feature', 'spec', 'design'].includes(commandName)) {
71
- return {
72
- type: 'missing_context',
73
- reason: 'No project analysis available, may need /p:sync first',
74
- priority: 'low',
75
- }
76
- }
77
-
78
- // Check for code patterns
79
- if (!state.codePatterns && ['now', 'build', 'fix'].includes(commandName)) {
80
- return {
81
- type: 'missing_patterns',
82
- reason: 'No code patterns detected, may produce inconsistent code',
83
- priority: 'low',
84
- }
85
- }
86
-
87
- return null
88
- }
89
-
90
- /**
91
- * Generate a think block
92
- */
93
- async function generate(
94
- trigger: ThinkTrigger,
95
- commandName: string,
96
- context: Context,
97
- state: State
98
- ): Promise<ThinkBlock> {
99
- const conclusions: string[] = []
100
- const plan: string[] = []
101
- let confidence = 0.8
102
-
103
- switch (trigger.type) {
104
- case 'critical_command':
105
- conclusions.push(`${commandName} requires careful execution`)
106
- conclusions.push('Will verify state before proceeding')
107
- plan.push('Check current state')
108
- plan.push('Verify prerequisites')
109
- plan.push('Execute with confirmation')
110
- plan.push('Verify results')
111
- confidence = 0.9
112
- break
113
-
114
- case 'complex_task':
115
- conclusions.push('Task appears complex, breaking down')
116
- conclusions.push('Will analyze dependencies first')
117
- plan.push('Parse task requirements')
118
- plan.push('Identify affected components')
119
- plan.push('Create execution plan')
120
- plan.push('Execute incrementally')
121
- confidence = 0.7
122
- break
123
-
124
- case 'task_conflict':
125
- conclusions.push('Existing task detected')
126
- conclusions.push('Should complete or pause current task first')
127
- plan.push('Check current task status')
128
- plan.push('Decide: complete, pause, or replace')
129
- plan.push('Update task state')
130
- plan.push('Proceed with new task')
131
- confidence = 0.6
132
- break
133
-
134
- case 'missing_context':
135
- conclusions.push('Project analysis not available')
136
- conclusions.push('May produce less optimal results')
137
- plan.push('Proceed with available context')
138
- plan.push('Note recommendation to run /p:sync')
139
- confidence = 0.5
140
- break
141
-
142
- case 'missing_patterns':
143
- conclusions.push('Code patterns not detected')
144
- conclusions.push('Will use best-effort pattern matching')
145
- plan.push('Read existing code for patterns')
146
- plan.push('Match detected style')
147
- plan.push('Generate consistent code')
148
- confidence = 0.6
149
- break
150
-
151
- default:
152
- conclusions.push('Standard execution path')
153
- plan.push('Execute command as specified')
154
- confidence = 0.8
155
- }
156
-
157
- return {
158
- trigger,
159
- commandName,
160
- conclusions,
161
- plan,
162
- confidence,
163
- generatedAt: new Date().toISOString(),
164
- }
165
- }
166
-
167
- /**
168
- * Format think block for display
169
- */
170
- function format(thinkBlock: ThinkBlock | null, verbose: boolean = false): string {
171
- if (!thinkBlock) {
172
- return ''
173
- }
174
-
175
- const lines: string[] = []
176
-
177
- if (verbose) {
178
- lines.push(`🧠 Think Block: ${thinkBlock.commandName}`)
179
- lines.push(`Trigger: ${thinkBlock.trigger.type} (${thinkBlock.trigger.priority})`)
180
- lines.push(`Reason: ${thinkBlock.trigger.reason}`)
181
- lines.push('')
182
- }
183
-
184
- lines.push('Conclusions:')
185
- thinkBlock.conclusions.forEach((c) => {
186
- lines.push(` → ${c}`)
187
- })
188
-
189
- lines.push('')
190
- lines.push('Plan:')
191
- thinkBlock.plan.forEach((p, i) => {
192
- lines.push(` ${i + 1}. ${p}`)
193
- })
194
-
195
- lines.push('')
196
- lines.push(`Confidence: ${Math.round(thinkBlock.confidence * 100)}%`)
197
-
198
- return lines.join('\n')
199
- }
200
-
201
- export { detectTrigger, generate, format }
202
- export default { detectTrigger, generate, format }