prjct-cli 0.10.9 → 0.10.11
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 +88 -0
- package/CLAUDE.md +121 -996
- package/core/__tests__/agentic/prompt-builder.test.js +7 -3
- package/core/agentic/prompt-builder.js +57 -56
- package/core/commands.js +29 -452
- package/core/domain/architecture-generator.js +51 -519
- package/core/domain/task-analyzer.js +11 -36
- package/package.json +1 -1
- package/templates/analysis/bug-severity.md +74 -0
- package/templates/analysis/complexity.md +54 -0
- package/templates/analysis/health.md +66 -0
- package/templates/analysis/intent.md +66 -0
- package/templates/analysis/patterns.md +27 -173
- package/templates/analysis/task-breakdown.md +53 -0
- package/templates/architect/discovery.md +67 -0
- package/templates/architect/phases.md +59 -0
- package/templates/commands/done.md +129 -15
- package/templates/commands/feature.md +262 -21
- package/templates/commands/ship.md +244 -23
- package/templates/commands/sync.md +235 -44
- package/templates/design/api.md +95 -0
- package/templates/design/architecture.md +77 -0
- package/templates/design/component.md +89 -0
- package/templates/design/database.md +78 -0
- package/templates/design/flow.md +94 -0
|
@@ -143,7 +143,9 @@ describe('PromptBuilder', () => {
|
|
|
143
143
|
|
|
144
144
|
const prompt = builder.build(template, context, state)
|
|
145
145
|
|
|
146
|
-
|
|
146
|
+
// OPTIMIZED: New compressed format uses ## FILES:
|
|
147
|
+
expect(prompt).toContain('## FILES:')
|
|
148
|
+
expect(prompt).toContain('3 available')
|
|
147
149
|
expect(prompt).toContain('file1.js')
|
|
148
150
|
expect(prompt).toContain('Read')
|
|
149
151
|
})
|
|
@@ -159,7 +161,8 @@ describe('PromptBuilder', () => {
|
|
|
159
161
|
|
|
160
162
|
const prompt = builder.build(template, context, state)
|
|
161
163
|
|
|
162
|
-
|
|
164
|
+
// OPTIMIZED: New compressed format uses ## PROJECT:
|
|
165
|
+
expect(prompt).toContain('## PROJECT:')
|
|
163
166
|
expect(prompt).toContain('/test/project')
|
|
164
167
|
})
|
|
165
168
|
})
|
|
@@ -188,7 +191,8 @@ describe('PromptBuilder', () => {
|
|
|
188
191
|
expect(prompt).toContain('TOOLS:')
|
|
189
192
|
expect(prompt).toContain('Flow')
|
|
190
193
|
expect(prompt).toContain('RULES (CRITICAL)')
|
|
191
|
-
|
|
194
|
+
// OPTIMIZED: New compressed format uses ## FILES:
|
|
195
|
+
expect(prompt).toContain('## FILES:')
|
|
192
196
|
})
|
|
193
197
|
|
|
194
198
|
it('should be concise (under 2000 chars for simple prompt)', () => {
|
|
@@ -24,41 +24,18 @@ class PromptBuilder {
|
|
|
24
24
|
// Store context for use in helper methods
|
|
25
25
|
this._currentContext = context
|
|
26
26
|
|
|
27
|
-
// Agent assignment (
|
|
28
|
-
//
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
if (agent.domain) {
|
|
40
|
-
parts.push(`Domain: ${agent.domain}\n`)
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
// Include skills if available
|
|
44
|
-
if (agent.skills && agent.skills.length > 0) {
|
|
45
|
-
parts.push(`Skills: ${agent.skills.join(', ')}\n`)
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
parts.push(`\n## AGENT INSTRUCTIONS\n`)
|
|
49
|
-
|
|
50
|
-
// CRITICAL: Include full agent content
|
|
51
|
-
// This is the specialized knowledge for this project
|
|
52
|
-
if (agent.content) {
|
|
53
|
-
parts.push(agent.content)
|
|
54
|
-
parts.push(`\n`)
|
|
55
|
-
} else if (agent.name) {
|
|
56
|
-
// Fallback if content not loaded
|
|
57
|
-
parts.push(`You are the ${agent.name} agent for this project.\n`)
|
|
58
|
-
parts.push(`Apply your specialized expertise to complete the task.\n\n`)
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
parts.push(`CONTEXT: ${context.filteredSize || 'all'} files (${context.reduction || 0}% reduced)\n\n`)
|
|
27
|
+
// Agent assignment (CONDITIONAL - only for code-modifying commands)
|
|
28
|
+
// Commands like done, ship, recap, next don't need specialized agents
|
|
29
|
+
const commandName = template.frontmatter?.name?.replace('p:', '') || ''
|
|
30
|
+
const agentCommands = ['now', 'build', 'feature', 'design', 'fix', 'bug', 'test', 'work', 'cleanup', 'spec']
|
|
31
|
+
const needsAgent = agentCommands.includes(commandName)
|
|
32
|
+
|
|
33
|
+
if (agent && needsAgent) {
|
|
34
|
+
// COMPRESSED: Only essential agent info (500 bytes vs 3-5KB)
|
|
35
|
+
parts.push(`# AGENT: ${agent.name}\n`)
|
|
36
|
+
if (agent.role) parts.push(`Role: ${agent.role}\n`)
|
|
37
|
+
if (agent.skills?.length) parts.push(`Skills: ${agent.skills.join(', ')}\n`)
|
|
38
|
+
parts.push(`\nApply specialized expertise. Read agent file for details if needed.\n\n`)
|
|
62
39
|
}
|
|
63
40
|
|
|
64
41
|
// Core instruction (concise)
|
|
@@ -93,38 +70,30 @@ class PromptBuilder {
|
|
|
93
70
|
parts.push('\n')
|
|
94
71
|
}
|
|
95
72
|
|
|
96
|
-
//
|
|
97
|
-
if (context.files
|
|
98
|
-
|
|
99
|
-
parts.push(
|
|
100
|
-
parts.push('
|
|
101
|
-
parts.push('\nTop relevant files:\n')
|
|
102
|
-
const topFiles = context.files.slice(0, 20).map(f => `- ${f}`).join('\n')
|
|
103
|
-
parts.push(topFiles)
|
|
104
|
-
if (context.files.length > 20) {
|
|
105
|
-
parts.push(`\n... and ${context.files.length - 20} more files. Use Read tool to access them.\n`)
|
|
106
|
-
}
|
|
107
|
-
parts.push('\n')
|
|
73
|
+
// COMPRESSED: File list (5 files vs 20, saves ~400 bytes)
|
|
74
|
+
if (context.files?.length > 0) {
|
|
75
|
+
const top5 = context.files.slice(0, 5).join(', ')
|
|
76
|
+
parts.push(`\n## FILES: ${context.files.length} available. Top: ${top5}\n`)
|
|
77
|
+
parts.push('Read BEFORE modifying. Use Glob/Grep to find more.\n\n')
|
|
108
78
|
} else if (context.projectPath) {
|
|
109
|
-
parts.push(
|
|
110
|
-
parts.push(`Project path: ${context.projectPath}\n`)
|
|
111
|
-
parts.push('**USE Read TOOL TO LOAD FILES YOU NEED TO UNDERSTAND OR MODIFY.**\n')
|
|
112
|
-
parts.push('**NEVER MODIFY CODE WITHOUT READING IT FIRST.**\n\n')
|
|
79
|
+
parts.push(`\n## PROJECT: ${context.projectPath}\nRead files before modifying.\n\n`)
|
|
113
80
|
}
|
|
114
81
|
|
|
115
82
|
// OPTIMIZED: Only include patterns for code-modifying commands
|
|
116
83
|
// Commands like done, ship, recap, next don't need full patterns
|
|
117
84
|
const codeCommands = ['now', 'build', 'feature', 'design', 'cleanup', 'fix', 'bug', 'test', 'init', 'spec', 'work']
|
|
118
|
-
const commandName = template.frontmatter?.name?.replace('p:', '') || ''
|
|
119
85
|
const needsPatterns = codeCommands.includes(commandName)
|
|
120
86
|
|
|
121
87
|
// Include code patterns analysis for code-modifying commands
|
|
88
|
+
// COMPRESSED: Extract only conventions and anti-patterns (800 bytes max vs 6KB)
|
|
122
89
|
const codePatternsContent = state?.codePatterns || ''
|
|
123
90
|
if (needsPatterns && codePatternsContent && codePatternsContent.trim()) {
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
91
|
+
const patternSummary = this.extractPatternSummary(codePatternsContent)
|
|
92
|
+
if (patternSummary) {
|
|
93
|
+
parts.push('\n## CODE PATTERNS\n')
|
|
94
|
+
parts.push(patternSummary)
|
|
95
|
+
parts.push('\nFull patterns: Read analysis/patterns.md\n')
|
|
96
|
+
}
|
|
128
97
|
}
|
|
129
98
|
|
|
130
99
|
const analysisContent = state?.analysis || ''
|
|
@@ -243,6 +212,38 @@ class PromptBuilder {
|
|
|
243
212
|
return parts.join('')
|
|
244
213
|
}
|
|
245
214
|
|
|
215
|
+
/**
|
|
216
|
+
* Extract pattern summary from full patterns content
|
|
217
|
+
* OPTIMIZED: Returns only conventions + high-priority anti-patterns (800 bytes max)
|
|
218
|
+
*/
|
|
219
|
+
extractPatternSummary(content) {
|
|
220
|
+
if (!content) return null
|
|
221
|
+
|
|
222
|
+
const parts = []
|
|
223
|
+
|
|
224
|
+
// Extract conventions section
|
|
225
|
+
const conventionsMatch = content.match(/## Conventions[\s\S]*?(?=##|$)/i)
|
|
226
|
+
if (conventionsMatch) {
|
|
227
|
+
// Compress to key lines only
|
|
228
|
+
const conventions = conventionsMatch[0]
|
|
229
|
+
.split('\n')
|
|
230
|
+
.filter(line => line.includes(':') || line.startsWith('-'))
|
|
231
|
+
.slice(0, 6)
|
|
232
|
+
.join('\n')
|
|
233
|
+
if (conventions) parts.push(conventions)
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
// Extract high priority anti-patterns only
|
|
237
|
+
const antiPatternsMatch = content.match(/### High Priority[\s\S]*?(?=###|##|$)/i)
|
|
238
|
+
if (antiPatternsMatch) {
|
|
239
|
+
const antiPatterns = antiPatternsMatch[0].substring(0, 300)
|
|
240
|
+
parts.push('\nAvoid:\n' + antiPatterns)
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
const result = parts.join('\n').substring(0, 800)
|
|
244
|
+
return result || null
|
|
245
|
+
}
|
|
246
|
+
|
|
246
247
|
/**
|
|
247
248
|
* Build critical rules - compressed anti-hallucination
|
|
248
249
|
* OPTIMIZED: From 66 lines to 12 lines (~82% reduction)
|