prjct-cli 0.8.8 → 0.9.2

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 (40) hide show
  1. package/CHANGELOG.md +194 -0
  2. package/core/__tests__/agentic/agent-router.test.js +398 -0
  3. package/core/__tests__/agentic/context-filter.test.js +494 -0
  4. package/core/__tests__/domain/analyzer.test.js +324 -0
  5. package/core/__tests__/infrastructure/author-detector.test.js +103 -0
  6. package/core/__tests__/infrastructure/config-manager.test.js +454 -0
  7. package/core/__tests__/infrastructure/path-manager.test.js +412 -0
  8. package/core/__tests__/utils/jsonl-helper.test.js +387 -0
  9. package/core/agentic/agent-router.js +482 -0
  10. package/core/agentic/command-executor.js +70 -15
  11. package/core/agentic/context-filter.js +549 -0
  12. package/core/agentic/prompt-builder.js +48 -38
  13. package/core/command-registry.js +104 -164
  14. package/core/domain/agent-generator.js +55 -44
  15. package/core/domain/architecture-generator.js +561 -0
  16. package/core/domain/task-stack.js +496 -0
  17. package/package.json +2 -1
  18. package/templates/commands/analyze.md +10 -53
  19. package/templates/commands/bug.md +11 -70
  20. package/templates/commands/build.md +7 -37
  21. package/templates/commands/cleanup.md +9 -32
  22. package/templates/commands/dash.md +241 -0
  23. package/templates/commands/design.md +5 -28
  24. package/templates/commands/done.md +6 -20
  25. package/templates/commands/feature.md +11 -83
  26. package/templates/commands/help.md +9 -38
  27. package/templates/commands/idea.md +7 -28
  28. package/templates/commands/init.md +10 -89
  29. package/templates/commands/next.md +6 -26
  30. package/templates/commands/now.md +6 -26
  31. package/templates/commands/pause.md +18 -0
  32. package/templates/commands/progress.md +5 -50
  33. package/templates/commands/recap.md +5 -54
  34. package/templates/commands/resume.md +97 -0
  35. package/templates/commands/ship.md +13 -68
  36. package/templates/commands/status.md +7 -32
  37. package/templates/commands/sync.md +7 -24
  38. package/templates/commands/work.md +44 -0
  39. package/templates/commands/workflow.md +3 -25
  40. package/templates/planning-methodology.md +195 -0
@@ -0,0 +1,549 @@
1
+ /**
2
+ * Intelligent Context Filtering System
3
+ *
4
+ * Reduces context window usage by 70-90% by loading only
5
+ * relevant files for each specialized agent
6
+ *
7
+ * @version 1.0.0
8
+ */
9
+
10
+ const fs = require('fs').promises;
11
+ const path = require('path');
12
+ const { glob } = require('glob');
13
+
14
+ class ContextFilter {
15
+ constructor() {
16
+ // Technology-specific file patterns
17
+ this.techPatterns = this.initializeTechPatterns();
18
+
19
+ // Task-based filtering rules
20
+ this.taskPatterns = this.initializeTaskPatterns();
21
+
22
+ // Cache for file analysis
23
+ this.fileCache = new Map();
24
+ }
25
+
26
+ /**
27
+ * Main entry point - filters context based on agent and task
28
+ */
29
+ async filterForAgent(agent, task, projectPath, fullContext = {}) {
30
+ const startTime = Date.now();
31
+
32
+ // Determine what files this agent needs
33
+ const relevantPatterns = await this.determineRelevantPatterns(
34
+ agent,
35
+ task,
36
+ projectPath
37
+ );
38
+
39
+ // Load only relevant files
40
+ const filteredFiles = await this.loadRelevantFiles(
41
+ projectPath,
42
+ relevantPatterns
43
+ );
44
+
45
+ // Calculate reduction metrics
46
+ const metrics = this.calculateMetrics(
47
+ fullContext.fileCount || 1000, // estimate if not provided
48
+ filteredFiles.length,
49
+ startTime
50
+ );
51
+
52
+ return {
53
+ files: filteredFiles,
54
+ patterns: relevantPatterns,
55
+ metrics,
56
+ agent: agent.name,
57
+ filtered: true
58
+ };
59
+ }
60
+
61
+ /**
62
+ * Initialize technology-specific patterns
63
+ */
64
+ initializeTechPatterns() {
65
+ return {
66
+ // Languages
67
+ javascript: {
68
+ extensions: ['.js', '.mjs', '.cjs'],
69
+ directories: ['src', 'lib', 'utils'],
70
+ exclude: ['node_modules', 'dist', 'build']
71
+ },
72
+ typescript: {
73
+ extensions: ['.ts', '.tsx', '.d.ts'],
74
+ directories: ['src', 'lib', 'types'],
75
+ exclude: ['node_modules', 'dist', 'build']
76
+ },
77
+ python: {
78
+ extensions: ['.py', '.pyx'],
79
+ directories: ['src', 'lib', 'app'],
80
+ exclude: ['__pycache__', 'venv', '.env']
81
+ },
82
+ ruby: {
83
+ extensions: ['.rb', '.rake'],
84
+ directories: ['app', 'lib', 'config'],
85
+ exclude: ['vendor', 'tmp', 'log']
86
+ },
87
+ go: {
88
+ extensions: ['.go'],
89
+ directories: ['pkg', 'cmd', 'internal'],
90
+ exclude: ['vendor', 'bin']
91
+ },
92
+ rust: {
93
+ extensions: ['.rs'],
94
+ directories: ['src', 'lib'],
95
+ exclude: ['target', 'dist']
96
+ },
97
+ java: {
98
+ extensions: ['.java'],
99
+ directories: ['src/main/java', 'src/test/java'],
100
+ exclude: ['target', 'build', '.gradle']
101
+ },
102
+ php: {
103
+ extensions: ['.php'],
104
+ directories: ['src', 'app', 'lib'],
105
+ exclude: ['vendor', 'cache']
106
+ },
107
+ elixir: {
108
+ extensions: ['.ex', '.exs'],
109
+ directories: ['lib', 'web', 'apps'],
110
+ exclude: ['_build', 'deps', 'cover']
111
+ },
112
+
113
+ // Frameworks
114
+ react: {
115
+ extensions: ['.jsx', '.tsx', '.js', '.ts'],
116
+ directories: ['components', 'pages', 'hooks', 'contexts'],
117
+ patterns: ['**/components/**', '**/pages/**', '**/hooks/**'],
118
+ exclude: ['node_modules', 'build', 'dist']
119
+ },
120
+ vue: {
121
+ extensions: ['.vue', '.js', '.ts'],
122
+ directories: ['components', 'views', 'stores'],
123
+ patterns: ['**/*.vue', '**/components/**'],
124
+ exclude: ['node_modules', 'dist']
125
+ },
126
+ angular: {
127
+ extensions: ['.ts', '.html', '.scss'],
128
+ directories: ['src/app'],
129
+ patterns: ['**/*.component.ts', '**/*.service.ts'],
130
+ exclude: ['node_modules', 'dist']
131
+ },
132
+ rails: {
133
+ extensions: ['.rb', '.erb', '.haml'],
134
+ directories: ['app', 'config', 'db'],
135
+ patterns: ['app/**/*.rb', 'config/**/*.rb'],
136
+ exclude: ['tmp', 'log', 'vendor']
137
+ },
138
+ django: {
139
+ extensions: ['.py', '.html'],
140
+ directories: ['apps', 'templates', 'static'],
141
+ patterns: ['**/*.py', 'templates/**'],
142
+ exclude: ['venv', '__pycache__', 'media']
143
+ },
144
+ express: {
145
+ extensions: ['.js', '.ts'],
146
+ directories: ['routes', 'controllers', 'middleware'],
147
+ patterns: ['routes/**', 'controllers/**'],
148
+ exclude: ['node_modules', 'public']
149
+ },
150
+ fastapi: {
151
+ extensions: ['.py'],
152
+ directories: ['app', 'api', 'routers'],
153
+ patterns: ['app/**/*.py', 'api/**/*.py'],
154
+ exclude: ['venv', '__pycache__']
155
+ },
156
+
157
+ // Databases
158
+ postgres: {
159
+ extensions: ['.sql', '.plpgsql'],
160
+ directories: ['migrations', 'schemas', 'functions'],
161
+ patterns: ['**/*.sql', 'migrations/**'],
162
+ exclude: []
163
+ },
164
+ mongodb: {
165
+ extensions: ['.js', '.ts', '.json'],
166
+ directories: ['models', 'schemas'],
167
+ patterns: ['models/**', 'schemas/**'],
168
+ exclude: []
169
+ },
170
+ mysql: {
171
+ extensions: ['.sql'],
172
+ directories: ['migrations', 'schemas'],
173
+ patterns: ['**/*.sql'],
174
+ exclude: []
175
+ }
176
+ };
177
+ }
178
+
179
+ /**
180
+ * Initialize task-based patterns
181
+ */
182
+ initializeTaskPatterns() {
183
+ return {
184
+ api: {
185
+ include: ['routes', 'controllers', 'middleware', 'api'],
186
+ patterns: ['**/api/**', '**/routes/**', '**/controllers/**'],
187
+ focus: 'backend logic and endpoints'
188
+ },
189
+ ui: {
190
+ include: ['components', 'pages', 'views', 'styles'],
191
+ patterns: ['**/components/**', '**/pages/**', '**/*.css', '**/*.scss'],
192
+ focus: 'user interface and styling'
193
+ },
194
+ database: {
195
+ include: ['models', 'migrations', 'schemas', 'db'],
196
+ patterns: ['**/models/**', '**/migrations/**', '**/*.sql'],
197
+ focus: 'data layer and persistence'
198
+ },
199
+ testing: {
200
+ include: ['test', 'tests', 'spec', '__tests__'],
201
+ patterns: ['**/*.test.*', '**/*.spec.*', '**/test/**'],
202
+ focus: 'test files and test utilities'
203
+ },
204
+ configuration: {
205
+ include: ['config', 'env', 'settings'],
206
+ patterns: ['**/config/**', '**/.env*', '**/*config.*'],
207
+ focus: 'configuration and environment'
208
+ },
209
+ deployment: {
210
+ include: ['.github', '.gitlab', 'docker', 'k8s'],
211
+ patterns: ['Dockerfile*', '**/*.yml', '**/*.yaml', '.github/**'],
212
+ focus: 'CI/CD and deployment'
213
+ },
214
+ documentation: {
215
+ include: ['docs', 'README'],
216
+ patterns: ['**/*.md', 'docs/**', 'README*'],
217
+ focus: 'documentation files'
218
+ }
219
+ };
220
+ }
221
+
222
+ /**
223
+ * Determine which patterns to use based on agent and task
224
+ */
225
+ async determineRelevantPatterns(agent, task, projectPath) {
226
+ const patterns = {
227
+ include: [],
228
+ exclude: [],
229
+ extensions: [],
230
+ specific: []
231
+ };
232
+
233
+ // Detect technologies in the project
234
+ const detectedTech = await this.detectProjectTechnologies(projectPath);
235
+
236
+ // Add patterns based on detected technologies
237
+ detectedTech.forEach(tech => {
238
+ if (this.techPatterns[tech]) {
239
+ const techPattern = this.techPatterns[tech];
240
+ patterns.extensions.push(...(techPattern.extensions || []));
241
+ patterns.include.push(...(techPattern.directories || []));
242
+ patterns.exclude.push(...(techPattern.exclude || []));
243
+ patterns.specific.push(...(techPattern.patterns || []));
244
+ }
245
+ });
246
+
247
+ // Add patterns based on task type
248
+ const taskType = this.detectTaskType(task);
249
+ if (this.taskPatterns[taskType]) {
250
+ const taskPattern = this.taskPatterns[taskType];
251
+ patterns.include.push(...(taskPattern.include || []));
252
+ patterns.specific.push(...(taskPattern.patterns || []));
253
+ }
254
+
255
+ // Add agent-specific patterns
256
+ const agentPatterns = this.getAgentSpecificPatterns(agent);
257
+ patterns.include.push(...agentPatterns.include);
258
+ patterns.exclude.push(...agentPatterns.exclude);
259
+
260
+ // Remove duplicates
261
+ patterns.include = [...new Set(patterns.include)];
262
+ patterns.exclude = [...new Set(patterns.exclude)];
263
+ patterns.extensions = [...new Set(patterns.extensions)];
264
+ patterns.specific = [...new Set(patterns.specific)];
265
+
266
+ return patterns;
267
+ }
268
+
269
+ /**
270
+ * Detect technologies used in the project
271
+ */
272
+ async detectProjectTechnologies(projectPath) {
273
+ const detected = new Set();
274
+
275
+ try {
276
+ // Check package.json for JS/TS projects
277
+ const packageJsonPath = path.join(projectPath, 'package.json');
278
+ if (await this.fileExists(packageJsonPath)) {
279
+ const packageJson = JSON.parse(await fs.readFile(packageJsonPath, 'utf8'));
280
+
281
+ // Check dependencies
282
+ const deps = {
283
+ ...packageJson.dependencies,
284
+ ...packageJson.devDependencies
285
+ };
286
+
287
+ // Detect frameworks
288
+ if (deps.react) detected.add('react');
289
+ if (deps.vue) detected.add('vue');
290
+ if (deps['@angular/core']) detected.add('angular');
291
+ if (deps.express) detected.add('express');
292
+ if (deps.next) detected.add('nextjs');
293
+ if (deps.fastify) detected.add('fastify');
294
+
295
+ // Language
296
+ if (deps.typescript) detected.add('typescript');
297
+ else detected.add('javascript');
298
+ }
299
+
300
+ // Check Gemfile for Ruby projects
301
+ const gemfilePath = path.join(projectPath, 'Gemfile');
302
+ if (await this.fileExists(gemfilePath)) {
303
+ detected.add('ruby');
304
+ const gemfile = await fs.readFile(gemfilePath, 'utf8');
305
+ if (gemfile.includes('rails')) detected.add('rails');
306
+ }
307
+
308
+ // Check requirements.txt or setup.py for Python
309
+ const requirementsPath = path.join(projectPath, 'requirements.txt');
310
+ const setupPyPath = path.join(projectPath, 'setup.py');
311
+ if (await this.fileExists(requirementsPath) || await this.fileExists(setupPyPath)) {
312
+ detected.add('python');
313
+
314
+ if (await this.fileExists(requirementsPath)) {
315
+ const requirements = await fs.readFile(requirementsPath, 'utf8');
316
+ if (requirements.includes('django')) detected.add('django');
317
+ if (requirements.includes('fastapi')) detected.add('fastapi');
318
+ if (requirements.includes('flask')) detected.add('flask');
319
+ }
320
+ }
321
+
322
+ // Check go.mod for Go projects
323
+ const goModPath = path.join(projectPath, 'go.mod');
324
+ if (await this.fileExists(goModPath)) {
325
+ detected.add('go');
326
+ }
327
+
328
+ // Check Cargo.toml for Rust
329
+ const cargoPath = path.join(projectPath, 'Cargo.toml');
330
+ if (await this.fileExists(cargoPath)) {
331
+ detected.add('rust');
332
+ }
333
+
334
+ // Check mix.exs for Elixir
335
+ const mixPath = path.join(projectPath, 'mix.exs');
336
+ if (await this.fileExists(mixPath)) {
337
+ detected.add('elixir');
338
+ }
339
+
340
+ // Check for Java/Maven/Gradle
341
+ const pomPath = path.join(projectPath, 'pom.xml');
342
+ const gradlePath = path.join(projectPath, 'build.gradle');
343
+ if (await this.fileExists(pomPath) || await this.fileExists(gradlePath)) {
344
+ detected.add('java');
345
+ }
346
+
347
+ // Check composer.json for PHP
348
+ const composerPath = path.join(projectPath, 'composer.json');
349
+ if (await this.fileExists(composerPath)) {
350
+ detected.add('php');
351
+ }
352
+
353
+ } catch (error) {
354
+ console.error('Error detecting technologies:', error.message);
355
+ }
356
+
357
+ return Array.from(detected);
358
+ }
359
+
360
+ /**
361
+ * Detect task type from description
362
+ */
363
+ detectTaskType(task) {
364
+ const description = (task.description || '').toLowerCase();
365
+
366
+ if (description.includes('api') || description.includes('endpoint')) {
367
+ return 'api';
368
+ }
369
+ if (description.includes('ui') || description.includes('component') || description.includes('style')) {
370
+ return 'ui';
371
+ }
372
+ if (description.includes('database') || description.includes('migration') || description.includes('schema')) {
373
+ return 'database';
374
+ }
375
+ if (description.includes('test') || description.includes('spec')) {
376
+ return 'testing';
377
+ }
378
+ if (description.includes('deploy') || description.includes('docker') || description.includes('ci')) {
379
+ return 'deployment';
380
+ }
381
+ if (description.includes('config') || description.includes('env')) {
382
+ return 'configuration';
383
+ }
384
+ if (description.includes('docs') || description.includes('readme')) {
385
+ return 'documentation';
386
+ }
387
+
388
+ return 'general';
389
+ }
390
+
391
+ /**
392
+ * Get agent-specific patterns
393
+ */
394
+ getAgentSpecificPatterns(agent) {
395
+ const agentType = (agent.type || agent.name || '').toLowerCase();
396
+
397
+ const patterns = {
398
+ 'frontend': {
399
+ include: ['components', 'pages', 'views', 'styles', 'public'],
400
+ exclude: ['backend', 'api', 'server', 'database']
401
+ },
402
+ 'backend': {
403
+ include: ['api', 'routes', 'controllers', 'services', 'middleware'],
404
+ exclude: ['components', 'styles', 'public']
405
+ },
406
+ 'database': {
407
+ include: ['models', 'schemas', 'migrations', 'db'],
408
+ exclude: ['components', 'styles', 'public', 'static']
409
+ },
410
+ 'devops': {
411
+ include: ['.github', '.gitlab', 'docker', 'k8s', 'terraform'],
412
+ exclude: ['src', 'app', 'components']
413
+ },
414
+ 'qa': {
415
+ include: ['test', 'tests', 'spec', '__tests__', 'cypress'],
416
+ exclude: ['src', 'app', 'public']
417
+ }
418
+ };
419
+
420
+ // Find matching pattern
421
+ for (const [key, pattern] of Object.entries(patterns)) {
422
+ if (agentType.includes(key)) {
423
+ return pattern;
424
+ }
425
+ }
426
+
427
+ // Default pattern
428
+ return {
429
+ include: [],
430
+ exclude: ['node_modules', 'vendor', 'dist', 'build', '.git']
431
+ };
432
+ }
433
+
434
+ /**
435
+ * Load only relevant files based on patterns
436
+ */
437
+ async loadRelevantFiles(projectPath, patterns) {
438
+ const files = [];
439
+
440
+ try {
441
+ // Build glob patterns
442
+ const globPatterns = this.buildGlobPatterns(patterns);
443
+
444
+ // Execute glob searches
445
+ for (const pattern of globPatterns) {
446
+ const matches = await glob(pattern, {
447
+ cwd: projectPath,
448
+ ignore: patterns.exclude,
449
+ nodir: true,
450
+ follow: false
451
+ });
452
+
453
+ // Ensure matches is always an array (glob v10+ returns array, but be defensive)
454
+ if (Array.isArray(matches)) {
455
+ files.push(...matches);
456
+ } else if (matches) {
457
+ // Convert iterable to array if needed
458
+ files.push(...Array.from(matches));
459
+ }
460
+ }
461
+
462
+ // Remove duplicates and sort
463
+ const uniqueFiles = [...new Set(files)].sort();
464
+
465
+ // Limit to reasonable number
466
+ const maxFiles = 100;
467
+ if (uniqueFiles.length > maxFiles) {
468
+ console.log(`Limiting context to ${maxFiles} most relevant files`);
469
+ return uniqueFiles.slice(0, maxFiles);
470
+ }
471
+
472
+ return uniqueFiles;
473
+
474
+ } catch (error) {
475
+ console.error('Error loading files:', error.message);
476
+ return [];
477
+ }
478
+ }
479
+
480
+ /**
481
+ * Build glob patterns from pattern configuration
482
+ */
483
+ buildGlobPatterns(patterns) {
484
+ const globs = [];
485
+
486
+ // Add specific patterns
487
+ globs.push(...patterns.specific);
488
+
489
+ // Add extension-based patterns
490
+ if (patterns.extensions.length > 0) {
491
+ const extPattern = `**/*{${patterns.extensions.join(',')}}`;
492
+ globs.push(extPattern);
493
+ }
494
+
495
+ // Add directory patterns
496
+ patterns.include.forEach(dir => {
497
+ globs.push(`${dir}/**/*`);
498
+ });
499
+
500
+ // Default pattern if none specified
501
+ if (globs.length === 0) {
502
+ globs.push('**/*.{js,ts,jsx,tsx,py,rb,go,java,php}');
503
+ }
504
+
505
+ return globs;
506
+ }
507
+
508
+ /**
509
+ * Calculate metrics for context reduction
510
+ */
511
+ calculateMetrics(originalCount, filteredCount, startTime) {
512
+ const reduction = originalCount > 0
513
+ ? Math.round(((originalCount - filteredCount) / originalCount) * 100)
514
+ : 0;
515
+
516
+ return {
517
+ originalFiles: originalCount,
518
+ filteredFiles: filteredCount,
519
+ reductionPercent: reduction,
520
+ processingTime: Date.now() - startTime,
521
+ effectiveness: reduction > 70 ? 'high' : reduction > 40 ? 'medium' : 'low'
522
+ };
523
+ }
524
+
525
+ /**
526
+ * Check if file exists
527
+ */
528
+ async fileExists(filePath) {
529
+ try {
530
+ await fs.access(filePath);
531
+ return true;
532
+ } catch {
533
+ return false;
534
+ }
535
+ }
536
+
537
+ /**
538
+ * Get filter statistics
539
+ */
540
+ getStatistics() {
541
+ return {
542
+ cachedFiles: this.fileCache.size,
543
+ supportedTechnologies: Object.keys(this.techPatterns).length,
544
+ taskTypes: Object.keys(this.taskPatterns).length
545
+ };
546
+ }
547
+ }
548
+
549
+ module.exports = ContextFilter;
@@ -6,61 +6,71 @@
6
6
 
7
7
  class PromptBuilder {
8
8
  /**
9
- * Build execution prompt for Claude
10
- * @param {Object} template - Template from template-loader
11
- * @param {Object} context - Context from context-builder
12
- * @param {Object} state - Current state from context-builder
13
- * @returns {string} Prompt for Claude
9
+ * Build concise prompt - only essentials
14
10
  */
15
- build(template, context, state) {
11
+ build(template, context, state, agent = null) {
16
12
  const parts = []
17
13
 
18
- // 1. Command instructions from template
19
- parts.push('# Command Instructions\n')
20
- parts.push(template.content)
21
- parts.push('\n')
14
+ // Agent assignment (if applicable)
15
+ if (agent) {
16
+ parts.push(`AGENT: ${agent.name}\n`)
17
+ parts.push(`CONTEXT: ${context.filteredSize || 'all'} files (${context.reduction || 0}% reduced)\n\n`)
18
+ }
19
+
20
+ // Core instruction (concise)
21
+ parts.push(`TASK: ${template.frontmatter.description}\n`)
22
22
 
23
- // 2. Allowed tools
23
+ // Tools (inline)
24
24
  if (template.frontmatter['allowed-tools']) {
25
- parts.push('## Allowed Tools\n')
26
- parts.push(`You can use: ${template.frontmatter['allowed-tools'].join(', ')}\n\n`)
25
+ parts.push(`TOOLS: ${template.frontmatter['allowed-tools'].join(', ')}\n`)
27
26
  }
28
27
 
29
- // 3. Project context
30
- parts.push('## Project Context\n')
31
- parts.push(`- Project ID: ${context.projectId}\n`)
32
- parts.push(`- Timestamp: ${context.timestamp}\n`)
33
- parts.push('\n')
28
+ // Critical parameters only
29
+ if (context.params?.task || context.params?.description) {
30
+ parts.push(`INPUT: ${context.params.task || context.params.description}\n`)
31
+ }
34
32
 
35
- // 4. Current state (only non-null files)
36
- parts.push('## Current State\n')
37
- for (const [key, content] of Object.entries(state)) {
38
- if (content && content.trim()) {
39
- parts.push(`### ${key}\n`)
40
- parts.push('```\n')
41
- parts.push(content)
42
- parts.push('\n```\n\n')
43
- }
33
+ parts.push('\n---\n')
34
+
35
+ // Template (only the flow section, skip verbose explanations)
36
+ const flowMatch = template.content.match(/## Flow([\s\S]*?)(?=##|$)/)
37
+ if (flowMatch) {
38
+ parts.push(flowMatch[0])
39
+ } else {
40
+ // Fallback to full template if no flow section
41
+ parts.push(template.content)
44
42
  }
45
43
 
46
- // 5. Command parameters
47
- if (Object.keys(context.params).length > 0) {
48
- parts.push('## Parameters\n')
49
- for (const [key, value] of Object.entries(context.params)) {
50
- parts.push(`- ${key}: ${value}\n`)
51
- }
44
+ // Current state (only if exists and relevant)
45
+ const relevantState = this.filterRelevantState(state)
46
+ if (relevantState) {
47
+ parts.push('\nSTATE:\n')
48
+ parts.push(relevantState)
52
49
  parts.push('\n')
53
50
  }
54
51
 
55
- // 6. Final instruction
56
- parts.push('## Execute\n')
57
- parts.push('Based on the instructions above, execute the command.\n')
58
- parts.push('Use ONLY the allowed tools.\n')
59
- parts.push('Make decisions based on context - do not follow rigid if/else rules.\n')
52
+ // Simple execution directive
53
+ parts.push('\nEXECUTE: Follow flow. Use tools. Decide.\n')
60
54
 
61
55
  return parts.join('')
62
56
  }
63
57
 
58
+ /**
59
+ * Filter only relevant state data
60
+ */
61
+ filterRelevantState(state) {
62
+ if (!state || Object.keys(state).length === 0) return null
63
+
64
+ const relevant = []
65
+ for (const [key, content] of Object.entries(state)) {
66
+ if (content && content.trim() && content.length < 500) {
67
+ relevant.push(`${key}: ${content.substring(0, 200)}`)
68
+ }
69
+ }
70
+
71
+ return relevant.length > 0 ? relevant.join('\n') : null
72
+ }
73
+
64
74
  /**
65
75
  * Build analysis prompt
66
76
  * Used for tasks that need Claude to analyze before acting