prjct-cli 0.8.6 → 0.9.1

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