prjct-cli 0.10.5 → 0.10.8
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 +83 -0
- package/core/__tests__/agentic/prompt-builder.test.js +244 -0
- package/core/__tests__/utils/output.test.js +163 -0
- package/core/agentic/agent-router.js +45 -173
- package/core/agentic/context-builder.js +20 -11
- package/core/agentic/context-filter.js +118 -313
- package/core/agentic/prompt-builder.js +79 -46
- package/core/commands.js +121 -637
- package/core/domain/agent-generator.js +55 -4
- package/core/domain/analyzer.js +122 -0
- package/core/domain/context-estimator.js +32 -53
- package/core/domain/smart-cache.js +2 -1
- package/core/domain/task-analyzer.js +75 -146
- package/core/domain/task-stack.js +2 -1
- package/core/utils/logger.js +64 -0
- package/core/utils/output.js +54 -0
- package/package.json +1 -1
- package/templates/agentic/agent-routing.md +78 -0
- package/templates/agentic/context-filtering.md +77 -0
- package/templates/analysis/project-analysis.md +78 -0
- package/templates/global/CLAUDE.md +137 -135
- package/core/domain/tech-detector.js +0 -365
|
@@ -20,6 +20,9 @@ class PromptBuilder {
|
|
|
20
20
|
*/
|
|
21
21
|
build(template, context, state, agent = null, learnedPatterns = null, thinkBlock = null, relevantMemories = null, planInfo = null) {
|
|
22
22
|
const parts = []
|
|
23
|
+
|
|
24
|
+
// Store context for use in helper methods
|
|
25
|
+
this._currentContext = context
|
|
23
26
|
|
|
24
27
|
// Agent assignment (if applicable)
|
|
25
28
|
// CRITICAL: Include full agent content, not just name
|
|
@@ -85,13 +88,49 @@ class PromptBuilder {
|
|
|
85
88
|
// Current state (only if exists and relevant)
|
|
86
89
|
const relevantState = this.filterRelevantState(state)
|
|
87
90
|
if (relevantState) {
|
|
88
|
-
parts.push('\
|
|
91
|
+
parts.push('\n## PRJCT STATE (Project Management Data)\n')
|
|
89
92
|
parts.push(relevantState)
|
|
90
93
|
parts.push('\n')
|
|
91
94
|
}
|
|
92
95
|
|
|
93
|
-
//
|
|
94
|
-
|
|
96
|
+
// CRITICAL: Include available project files for context
|
|
97
|
+
if (context.files && context.files.length > 0) {
|
|
98
|
+
parts.push('\n## AVAILABLE PROJECT FILES\n')
|
|
99
|
+
parts.push(`You have ${context.files.length} relevant files available in this project.\n`)
|
|
100
|
+
parts.push('**USE Read TOOL TO LOAD FILES BEFORE MODIFYING THEM.**\n')
|
|
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')
|
|
108
|
+
} else if (context.projectPath) {
|
|
109
|
+
parts.push('\n## PROJECT FILES\n')
|
|
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')
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// OPTIMIZED: Only include patterns for code-modifying commands
|
|
116
|
+
// Commands like now, done, ship, recap, next don't need full patterns
|
|
117
|
+
const codeCommands = ['build', 'feature', 'design', 'cleanup', 'fix', 'bug', 'test', 'init']
|
|
118
|
+
const commandName = template.frontmatter?.name?.replace('p:', '') || ''
|
|
119
|
+
const needsPatterns = codeCommands.includes(commandName)
|
|
120
|
+
|
|
121
|
+
const analysisContent = state?.analysis || ''
|
|
122
|
+
if (needsPatterns && analysisContent && analysisContent.trim()) {
|
|
123
|
+
// Extract stack info compactly
|
|
124
|
+
const stackMatch = analysisContent.match(/Stack[:\s]+([^\n]+)/i) ||
|
|
125
|
+
analysisContent.match(/Technology[:\s]+([^\n]+)/i)
|
|
126
|
+
const stack = stackMatch ? stackMatch[1].trim() : 'detected'
|
|
127
|
+
|
|
128
|
+
parts.push(`\n## PATTERNS\nStack: ${stack}\n`)
|
|
129
|
+
parts.push('Read analysis/repo-summary.md + similar files before coding. Match patterns exactly.\n')
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// CRITICAL: Compressed rules (replaces 78 lines with 12)
|
|
133
|
+
parts.push(this.buildCriticalRules());
|
|
95
134
|
|
|
96
135
|
// P1.1: Learned Patterns (avoid asking user questions we already know)
|
|
97
136
|
if (learnedPatterns && Object.keys(learnedPatterns).some(k => learnedPatterns[k])) {
|
|
@@ -126,37 +165,13 @@ class PromptBuilder {
|
|
|
126
165
|
}
|
|
127
166
|
}
|
|
128
167
|
|
|
129
|
-
// P3.4: Plan Mode
|
|
130
|
-
if (planInfo) {
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
parts.push('3. **ANALYZE**: Understand the context and implications\n')
|
|
137
|
-
parts.push('4. **PROPOSE**: Generate a plan with clear steps\n')
|
|
138
|
-
parts.push('5. **WAIT FOR APPROVAL**: Do NOT execute until user approves\n')
|
|
139
|
-
|
|
140
|
-
if (planInfo.active) {
|
|
141
|
-
parts.push(`\nCurrent Status: ${planInfo.active.status}\n`)
|
|
142
|
-
if (planInfo.active.gatheredInfo?.length > 0) {
|
|
143
|
-
parts.push(`Info gathered: ${planInfo.active.gatheredInfo.length} items\n`)
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
if (planInfo.requiresApproval) {
|
|
149
|
-
parts.push('\n## APPROVAL REQUIRED\n')
|
|
150
|
-
parts.push('This command is DESTRUCTIVE. You MUST:\n')
|
|
151
|
-
parts.push('1. Show exactly what will change\n')
|
|
152
|
-
parts.push('2. List affected files/resources\n')
|
|
153
|
-
parts.push('3. Ask for explicit user confirmation (y/n)\n')
|
|
154
|
-
parts.push('4. Only proceed after approval\n')
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
if (planInfo.allowedTools) {
|
|
158
|
-
parts.push(`\nAllowed tools: ${planInfo.allowedTools.join(', ')}\n`)
|
|
159
|
-
}
|
|
168
|
+
// P3.4: Plan Mode (OPTIMIZED: 30 lines → 5 lines)
|
|
169
|
+
if (planInfo?.isPlanning) {
|
|
170
|
+
parts.push(`\n## PLAN MODE\nRead-only. Gather info → Analyze → Propose plan → Wait for approval.\n`)
|
|
171
|
+
if (planInfo.allowedTools) parts.push(`Tools: ${planInfo.allowedTools.join(', ')}\n`)
|
|
172
|
+
}
|
|
173
|
+
if (planInfo?.requiresApproval) {
|
|
174
|
+
parts.push(`\n## APPROVAL REQUIRED\nShow changes, list affected files, ask for confirmation.\n`)
|
|
160
175
|
}
|
|
161
176
|
|
|
162
177
|
// Simple execution directive
|
|
@@ -167,18 +182,33 @@ class PromptBuilder {
|
|
|
167
182
|
|
|
168
183
|
/**
|
|
169
184
|
* Filter only relevant state data
|
|
185
|
+
* IMPROVED: Include more context, don't truncate critical info
|
|
170
186
|
*/
|
|
171
187
|
filterRelevantState(state) {
|
|
172
188
|
if (!state || Object.keys(state).length === 0) return null
|
|
173
189
|
|
|
174
190
|
const relevant = []
|
|
175
191
|
for (const [key, content] of Object.entries(state)) {
|
|
176
|
-
if (content && content.trim()
|
|
177
|
-
|
|
192
|
+
if (content && content.trim()) {
|
|
193
|
+
// Include full content for critical files (now, next, context)
|
|
194
|
+
const criticalFiles = ['now', 'next', 'context', 'analysis']
|
|
195
|
+
if (criticalFiles.includes(key)) {
|
|
196
|
+
// Include full content for critical files (up to 2000 chars)
|
|
197
|
+
const display = content.length > 2000
|
|
198
|
+
? content.substring(0, 2000) + '\n... (truncated)'
|
|
199
|
+
: content
|
|
200
|
+
relevant.push(`### ${key}\n${display}`)
|
|
201
|
+
} else if (content.length < 1000) {
|
|
202
|
+
// Include full content for small files
|
|
203
|
+
relevant.push(`### ${key}\n${content}`)
|
|
204
|
+
} else {
|
|
205
|
+
// Truncate large files but show more context
|
|
206
|
+
relevant.push(`### ${key}\n${content.substring(0, 500)}... (truncated, use Read tool for full content)`)
|
|
207
|
+
}
|
|
178
208
|
}
|
|
179
209
|
}
|
|
180
210
|
|
|
181
|
-
return relevant.length > 0 ? relevant.join('\n') : null
|
|
211
|
+
return relevant.length > 0 ? relevant.join('\n\n') : null
|
|
182
212
|
}
|
|
183
213
|
|
|
184
214
|
/**
|
|
@@ -203,19 +233,22 @@ class PromptBuilder {
|
|
|
203
233
|
}
|
|
204
234
|
|
|
205
235
|
/**
|
|
206
|
-
* Build
|
|
207
|
-
*
|
|
236
|
+
* Build critical rules - compressed anti-hallucination
|
|
237
|
+
* OPTIMIZED: From 66 lines to 12 lines (~82% reduction)
|
|
208
238
|
*/
|
|
209
|
-
|
|
239
|
+
buildCriticalRules() {
|
|
240
|
+
const fileCount = this._currentContext?.files?.length || this._currentContext?.filteredSize || 0
|
|
210
241
|
return `
|
|
211
|
-
##
|
|
212
|
-
1.
|
|
213
|
-
2.
|
|
214
|
-
3.
|
|
215
|
-
4.
|
|
216
|
-
5.
|
|
242
|
+
## RULES (CRITICAL)
|
|
243
|
+
1. **READ FIRST**: Use Read tool BEFORE modifying any file. Never assume code structure.
|
|
244
|
+
2. **MATCH PATTERNS**: Follow existing style, architecture, naming, imports exactly.
|
|
245
|
+
3. **NO HALLUCINATIONS**: Don't invent files, functions, or paths. If unsure, READ first.
|
|
246
|
+
4. **GIT SAFETY**: Never use checkout/reset --hard/clean. Always check status first.
|
|
247
|
+
5. **VERIFY**: After writing, confirm code matches project patterns.
|
|
248
|
+
Context: ${fileCount} files available. Read what you need.
|
|
217
249
|
`;
|
|
218
250
|
}
|
|
251
|
+
|
|
219
252
|
}
|
|
220
253
|
|
|
221
254
|
module.exports = new PromptBuilder()
|