claude-flow-novice 2.15.10 → 2.15.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.
Files changed (47) hide show
  1. package/claude-assets/agents/cfn-dev-team/CLAUDE.md +9 -81
  2. package/claude-assets/agents/cfn-dev-team/architecture/base-template-generator.md +4 -4
  3. package/claude-assets/agents/cfn-dev-team/architecture/planner.md +4 -4
  4. package/claude-assets/agents/cfn-dev-team/architecture/system-architect.md +5 -5
  5. package/claude-assets/agents/cfn-dev-team/coordinators/cfn-v3-coordinator.md +5 -1
  6. package/claude-assets/agents/cfn-dev-team/dev-ops/devops-engineer.md +4 -4
  7. package/claude-assets/agents/cfn-dev-team/dev-ops/docker-specialist.md +7 -37
  8. package/claude-assets/agents/cfn-dev-team/dev-ops/kubernetes-specialist.md +7 -37
  9. package/claude-assets/agents/cfn-dev-team/dev-ops/monitoring-specialist.md +4 -4
  10. package/claude-assets/agents/cfn-dev-team/developers/api-gateway-specialist.md +11 -42
  11. package/claude-assets/agents/cfn-dev-team/product-owners/accessibility-advocate-persona.md +4 -4
  12. package/claude-assets/agents/cfn-dev-team/product-owners/cto-agent.md +4 -4
  13. package/claude-assets/agents/cfn-dev-team/product-owners/power-user-persona.md +4 -4
  14. package/claude-assets/agents/cfn-dev-team/product-owners/product-owner.md +18 -22
  15. package/claude-assets/agents/cfn-dev-team/reviewers/code-reviewer.md +1 -1
  16. package/claude-assets/agents/cfn-dev-team/reviewers/quality/code-quality-validator.md +1 -1
  17. package/claude-assets/agents/cfn-dev-team/reviewers/quality/perf-analyzer.md +1 -1
  18. package/claude-assets/agents/cfn-dev-team/reviewers/quality/performance-benchmarker.md +1 -1
  19. package/claude-assets/agents/cfn-dev-team/reviewers/quality/security-specialist.md +1 -1
  20. package/claude-assets/agents/cfn-dev-team/testers/api-testing-specialist.md +7 -35
  21. package/claude-assets/agents/cfn-dev-team/testers/chaos-engineering-specialist.md +17 -36
  22. package/claude-assets/agents/cfn-dev-team/testers/contract-tester.md +10 -11
  23. package/claude-assets/agents/cfn-dev-team/testers/e2e/playwright-tester.md +5 -5
  24. package/claude-assets/agents/cfn-dev-team/testers/integration-tester.md +10 -12
  25. package/claude-assets/agents/cfn-dev-team/testers/interaction-tester.md +7 -36
  26. package/claude-assets/agents/cfn-dev-team/testers/load-testing-specialist.md +10 -12
  27. package/claude-assets/agents/cfn-dev-team/testers/mutation-testing-specialist.md +10 -12
  28. package/claude-assets/agents/cfn-dev-team/testers/playwright-tester.md +7 -37
  29. package/claude-assets/agents/cfn-dev-team/testers/tester.md +7 -33
  30. package/claude-assets/agents/cfn-dev-team/testers/unit/tdd-london-unit-swarm.md +5 -5
  31. package/claude-assets/agents/cfn-dev-team/testers/validation/validation-production-validator.md +4 -4
  32. package/claude-assets/agents/cfn-dev-team/testing/test-validation-agent.md +4 -4
  33. package/claude-assets/agents/cfn-dev-team/utility/agent-builder.md +16 -16
  34. package/claude-assets/agents/cfn-dev-team/utility/analyst.md +4 -4
  35. package/claude-assets/agents/cfn-dev-team/utility/code-booster.md +4 -4
  36. package/claude-assets/agents/cfn-dev-team/utility/context-curator.md +4 -4
  37. package/claude-assets/agents/cfn-dev-team/utility/epic-creator.md +7 -92
  38. package/claude-assets/agents/cfn-dev-team/utility/memory-leak-specialist.md +7 -100
  39. package/claude-assets/agents/cfn-dev-team/utility/researcher.md +4 -4
  40. package/claude-assets/agents/cfn-dev-team/utility/z-ai-specialist.md +7 -91
  41. package/dist/cli/agent-definition-parser.js +37 -4
  42. package/dist/cli/agent-definition-parser.js.map +1 -1
  43. package/dist/cli/agent-executor.js +32 -2
  44. package/dist/cli/agent-executor.js.map +1 -1
  45. package/dist/cli/config-manager.js +109 -91
  46. package/dist/cli/config-manager.js.map +1 -1
  47. package/package.json +1 -1
@@ -23,76 +23,6 @@ provider: zai
23
23
  model: glm-4.6
24
24
  -->
25
25
 
26
- ## Success Criteria Awareness (REQUIRED - Phase 2 TDD)
27
-
28
- **How Success Criteria Are Passed:**
29
- - Environment Variable: `AGENT_SUCCESS_CRITERIA` (JSON string)
30
- - Set by: CFN Loop orchestrator (`.claude/skills/cfn-loop-orchestration/orchestrate.sh`)
31
- - Responsibility: Orchestrator injects criteria before spawning agent
32
- - Format: `{"test_suites": [{"name": "...", "command": "...", "pass_threshold": 0.95}]}`
33
-
34
- ### 1. Read Success Criteria
35
- Before starting work, read test requirements from environment:
36
- ```bash
37
- if [[ -n "${AGENT_SUCCESS_CRITERIA:-}" ]]; then
38
- # Validate JSON before parsing
39
- if ! echo "$AGENT_SUCCESS_CRITERIA" | jq -e '.' >/dev/null 2>&1; then
40
- echo "❌ Invalid JSON in AGENT_SUCCESS_CRITERIA" >&2
41
- exit 1
42
- fi
43
-
44
- CRITERIA=$(echo "$AGENT_SUCCESS_CRITERIA" | jq -r '.')
45
- TEST_SUITES=$(echo "$CRITERIA" | jq -r '.test_suites[] // empty')
46
-
47
- if [[ -n "$TEST_SUITES" ]]; then
48
- echo "📋 Success Criteria Loaded:"
49
- echo "$TEST_SUITES" | jq -r '.name // "unnamed"'
50
- fi
51
- fi
52
- ```
53
-
54
- ### 2. TDD Protocol (MANDATORY)
55
-
56
- **Write Tests First:**
57
- - Extract test requirements from success criteria
58
- - Write failing tests for each requirement
59
- - Ensure test coverage ≥80%
60
- - *Time Guideline (not hard constraint): ~15-20 min typical, adjust freely based on memory profiling complexity and heap dump analysis*
61
-
62
- **Implement:**
63
- - Write minimum code to pass tests
64
- - Run tests continuously (`npm test --watch` or framework equivalent)
65
- - Refactor for quality
66
- - *Guidance: Typically ~30-40 min, memory profiling may extend this*
67
-
68
- **Validate:**
69
- - Run full test suite: `npm test` (or framework command from criteria)
70
- - Verify pass rate meets threshold (Standard: ≥95%)
71
- - Check coverage: `npm run coverage`
72
- - *Guidance: Typically ~5 min for validation*
73
-
74
- ### 3. Report Test Results (NOT Confidence)
75
-
76
- **Old (Deprecated):**
77
- ```bash
78
- # report-completion.sh --confidence 0.85
79
- ```
80
-
81
- **New (Required):**
82
- ```bash
83
- # Execute tests and capture output
84
- TEST_OUTPUT=$(npm test 2>&1)
85
-
86
- # Parse natively (no external dependencies)
87
- PASS=$(echo "$TEST_OUTPUT" | grep -oP '\d+(?= passing)' || echo "0")
88
- FAIL=$(echo "$TEST_OUTPUT" | grep -oP '\d+(?= failing)' || echo "0")
89
- TOTAL=$((PASS + FAIL))
90
- RATE=$(awk "BEGIN {if ($TOTAL > 0) printf \"%.2f\", $PASS/$TOTAL; else print \"0.00\"}")
91
-
92
- # Return results (Main Chat receives automatically in Task Mode)
93
- echo "{\"passed\": $PASS, \"failed\": $FAIL, \"pass_rate\": $RATE}"
94
- ```
95
-
96
26
  # Memory Leak Specialist Agent
97
27
 
98
28
  ## Core Responsibilities
@@ -816,38 +746,15 @@ Before reporting high confidence:
816
746
  - Heap utilization optimized (<80% of max)
817
747
  - Confidence score ≥ 0.90
818
748
 
819
- ## Completion Protocol (Test-Driven)
820
-
821
- Complete your work and provide test-based validation:
822
-
823
- 1. **Execute Tests**: Run all test suites from success criteria
824
- 2. **Parse Results**: Extract pass/fail counts and calculate pass rate
825
- ```bash
826
- # Parse natively (no external dependencies)
827
- PASS=$(echo "$TEST_OUTPUT" | grep -oP '\d+(?= passing)' || echo "0")
828
- FAIL=$(echo "$TEST_OUTPUT" | grep -oP '\d+(?= failing)' || echo "0")
829
- TOTAL=$((PASS + FAIL))
830
- RATE=$(awk "BEGIN {if ($TOTAL > 0) printf \"%.2f\", $PASS/$TOTAL; else print \"0.00\"}")
749
+ ## Completion Protocol
831
750
 
832
- # Return results (Main Chat receives automatically in Task Mode)
833
- echo "{\"passed\": $PASS, \"failed\": $FAIL, \"pass_rate\": $RATE}"
834
- ```
835
- 3. **Verify Coverage**: ≥80%
836
- 4. **Store in Redis**: Use test-results key (not confidence key)
837
- 5. **Signal Completion**: Push to completion queue
838
-
839
- **Example Report:**
840
- ```
841
- Test Execution Summary:
842
- - Leak Detection Tests: 45/47 passed (95.7%)
843
- - Heap Analysis Tests: 12/12 passed (100%)
844
- - Profiling Tests: 8/10 passed (80%)
845
- - Overall: 65/69 passed (94.2%)
846
- - Coverage: 84.3%
847
- - Gate Status: PASS (≥95% in 2/3 suites, ≥80% overall)
848
- ```
751
+ Complete your work and provide a structured response with:
752
+ - Confidence score (0.0-1.0) based on work quality
753
+ - Summary of work completed
754
+ - List of deliverables created
755
+ - Any recommendations or findings
849
756
 
850
- **Note:** Coordination instructions and success criteria provided when spawned via CLI.
757
+ **Note:** Coordination handled automatically by the system.
851
758
 
852
759
  ## Skill References
853
760
  → **Node.js Profiling**: `.claude/skills/nodejs-memory-profiling/SKILL.md`
@@ -100,11 +100,11 @@ confidence = (
100
100
 
101
101
  Complete your work and provide a structured response with:
102
102
  - Confidence score (0.0-1.0) based on work quality
103
- - Summary of analysis/review completed
104
- - List of findings or deliverables
105
- - Any recommendations made
103
+ - Summary of work completed
104
+ - List of deliverables created
105
+ - Any recommendations or findings
106
106
 
107
- **Note:** Coordination instructions are provided when spawned via CLI.
107
+ **Note:** Coordination handled automatically by the system.
108
108
 
109
109
  ## Post-Edit Hook Validation
110
110
 
@@ -22,67 +22,6 @@ provider: zai
22
22
  model: glm-4.6
23
23
  -->
24
24
 
25
- ## Success Criteria Awareness (REQUIRED - Phase 2 TDD)
26
-
27
- ### 1. Read Success Criteria
28
- Before starting work, read test requirements from environment:
29
- ```bash
30
- if [[ -n "${AGENT_SUCCESS_CRITERIA:-}" ]]; then
31
- # Validate JSON before parsing
32
- if ! echo "$AGENT_SUCCESS_CRITERIA" | jq -e '.' >/dev/null 2>&1; then
33
- echo "❌ Invalid JSON in AGENT_SUCCESS_CRITERIA" >&2
34
- exit 1
35
- fi
36
-
37
- CRITERIA=$(echo "$AGENT_SUCCESS_CRITERIA" | jq -r '.')
38
- TEST_SUITES=$(echo "$CRITERIA" | jq -r '.test_suites[] // empty')
39
-
40
- if [[ -n "$TEST_SUITES" ]]; then
41
- echo "📋 Success Criteria Loaded:"
42
- echo "$TEST_SUITES" | jq -r '.name // "unnamed"'
43
- fi
44
- fi
45
- ```
46
-
47
- ### 2. TDD Protocol (MANDATORY)
48
-
49
- **Write Tests First (15-20 min):**
50
- - Extract test requirements from success criteria
51
- - Write failing tests for each requirement
52
- - Ensure test coverage ≥80%
53
-
54
- **Implement (30-40 min):**
55
- - Write minimum code to pass tests
56
- - Run tests continuously (`npm test --watch` or framework equivalent)
57
- - Refactor for quality
58
-
59
- **Validate (5 min):**
60
- - Run full test suite: `npm test` (or framework command from criteria)
61
- - Verify pass rate meets threshold (Standard: ≥95%)
62
- - Check coverage: `npm run coverage`
63
-
64
- ### 3. Report Test Results (NOT Confidence)
65
-
66
- **Old (Deprecated):**
67
- ```bash
68
- # report-completion.sh --confidence 0.85
69
- ```
70
-
71
- **New (Required):**
72
- ```bash
73
- # Execute tests and capture output
74
- TEST_OUTPUT=$(npm test 2>&1)
75
-
76
- # Parse natively (no external dependencies)
77
- PASS=$(echo "$TEST_OUTPUT" | grep -oP '\d+(?= passing)' || echo "0")
78
- FAIL=$(echo "$TEST_OUTPUT" | grep -oP '\d+(?= failing)' || echo "0")
79
- TOTAL=$((PASS + FAIL))
80
- RATE=$(awk "BEGIN {if ($TOTAL > 0) printf \"%.2f\", $PASS/$TOTAL; else print \"0.00\"}")
81
-
82
- # Return results (Main Chat receives automatically in Task Mode)
83
- echo "{\"passed\": $PASS, \"failed\": $FAIL, \"pass_rate\": $RATE}"
84
- ```
85
-
86
25
  # Z.ai Specialist Agent
87
26
 
88
27
  ## Core Responsibilities
@@ -680,38 +619,15 @@ Before reporting high confidence:
680
619
  - Usage tracking accurate (100% requests logged)
681
620
  - Confidence score ≥ 0.90
682
621
 
683
- ## Completion Protocol (Test-Driven)
622
+ ## Completion Protocol
684
623
 
685
- Complete your work and provide test-based validation:
686
-
687
- 1. **Execute Tests**: Run all test suites from success criteria
688
- 2. **Parse Results**: Extract pass/fail counts and calculate pass rate
689
- ```bash
690
- # Parse natively (no external dependencies)
691
- PASS=$(echo "$TEST_OUTPUT" | grep -oP '\d+(?= passing)' || echo "0")
692
- FAIL=$(echo "$TEST_OUTPUT" | grep -oP '\d+(?= failing)' || echo "0")
693
- TOTAL=$((PASS + FAIL))
694
- RATE=$(awk "BEGIN {if ($TOTAL > 0) printf \"%.2f\", $PASS/$TOTAL; else print \"0.00\"}")
695
-
696
- # Return results (Main Chat receives automatically in Task Mode)
697
- echo "{\"passed\": $PASS, \"failed\": $FAIL, \"pass_rate\": $RATE}"
698
- ```
699
- 3. **Verify Coverage**: ≥80%
700
- 4. **Store in Redis**: Use test-results key (not confidence key)
701
- 5. **Signal Completion**: Push to completion queue
702
-
703
- **Example Report:**
704
- ```
705
- Test Execution Summary:
706
- - Configuration Tests: 45/47 passed (95.7%)
707
- - Routing Tests: 12/12 passed (100%)
708
- - Cost Analysis Tests: 8/10 passed (80%)
709
- - Overall: 65/69 passed (94.2%)
710
- - Coverage: 84.3%
711
- - Gate Status: PASS (≥95% in 2/3 suites, ≥80% overall)
712
- ```
624
+ Complete your work and provide a structured response with:
625
+ - Confidence score (0.0-1.0) based on work quality
626
+ - Summary of work completed
627
+ - List of deliverables created
628
+ - Any recommendations or findings
713
629
 
714
- **Note:** Coordination instructions and success criteria provided when spawned via CLI.
630
+ **Note:** Coordination handled automatically by the system.
715
631
 
716
632
  ## Skill References
717
633
  → **Z.ai Setup**: `.claude/skills/zai-platform-setup/SKILL.md`
@@ -7,9 +7,39 @@
7
7
  import path from 'path';
8
8
  import { fileURLToPath } from 'url';
9
9
  import { glob } from 'glob';
10
+ import { execSync } from 'child_process';
10
11
  // ES Module compatibility
11
12
  const __filename = fileURLToPath(import.meta.url);
12
13
  const __dirname = path.dirname(__filename);
14
+ /**
15
+ * Detect project root dynamically
16
+ * Uses PROJECT_ROOT env var if set, otherwise tries git, falls back to cwd
17
+ */ function getProjectRoot() {
18
+ // 1. Check environment variable
19
+ if (process.env.PROJECT_ROOT) {
20
+ return process.env.PROJECT_ROOT;
21
+ }
22
+ // 2. Try git rev-parse (most reliable)
23
+ try {
24
+ const gitRoot = execSync('git rev-parse --show-toplevel', {
25
+ encoding: 'utf-8',
26
+ cwd: process.cwd(),
27
+ stdio: [
28
+ 'pipe',
29
+ 'pipe',
30
+ 'ignore'
31
+ ]
32
+ }).trim();
33
+ if (gitRoot) {
34
+ return gitRoot;
35
+ }
36
+ } catch {
37
+ // Fall through to next method
38
+ }
39
+ // 3. Fall back to current working directory
40
+ return process.cwd();
41
+ }
42
+ const projectRoot = getProjectRoot();
13
43
  /**
14
44
  * Parse YAML frontmatter from markdown content
15
45
  * Supports both Unix (LF) and Windows (CRLF) line endings
@@ -111,13 +141,15 @@ const __dirname = path.dirname(__filename);
111
141
  /**
112
142
  * Find agent definition file by agent type/name
113
143
  * Searches multiple locations for agent definitions
114
- */ async function findAgentFile(agentType, baseDir = '.claude/agents') {
144
+ */ async function findAgentFile(agentType, baseDir) {
115
145
  // Normalize agent type (handle both kebab-case and underscores)
116
146
  const normalizedType = agentType.toLowerCase().replace(/_/g, '-');
117
147
  // Search locations (in order of priority)
148
+ // Use provided baseDir, or construct default path from project root
149
+ const defaultBaseDir = path.join(projectRoot, '.claude/agents');
118
150
  const searchLocations = [
119
- baseDir,
120
- '.claude/agents',
151
+ baseDir || defaultBaseDir,
152
+ defaultBaseDir,
121
153
  path.join(__dirname, '../../.claude/agents'),
122
154
  '/app/.claude/agents'
123
155
  ];
@@ -164,7 +196,8 @@ const __dirname = path.dirname(__filename);
164
196
  // Parse frontmatter and body
165
197
  const { frontmatter, body } = parseFrontmatter(content);
166
198
  // Extract category from path
167
- const relativePath = path.relative('.claude/agents', filePath);
199
+ const agentsPath = path.join(projectRoot, '.claude/agents');
200
+ const relativePath = path.relative(agentsPath, filePath);
168
201
  const category = relativePath.includes('/') ? relativePath.split('/')[0] : undefined;
169
202
  // Build agent definition
170
203
  const definition = {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/cli/agent-definition-parser.ts"],"sourcesContent":["/**\r\n * Agent Definition Parser\r\n *\r\n * Parses agent definition files (.md) with YAML frontmatter and markdown content.\r\n * Supports agent definitions in .claude/agents/ directory structure.\r\n */\r\n\r\nimport fs from 'fs/promises';\r\nimport path from 'path';\r\nimport { fileURLToPath } from 'url';\r\nimport { glob } from 'glob';\r\n\r\n// ES Module compatibility\r\nconst __filename = fileURLToPath(import.meta.url);\r\nconst __dirname = path.dirname(__filename);\r\n\r\nexport interface AgentDefinition {\r\n // YAML frontmatter fields\r\n name: string;\r\n description: string;\r\n tools: string[];\r\n model: 'haiku' | 'sonnet' | 'opus';\r\n type?: string;\r\n color?: string;\r\n acl_level?: number;\r\n capabilities?: string[];\r\n validation_hooks?: string[];\r\n lifecycle?: {\r\n pre_task?: string;\r\n post_task?: string;\r\n };\r\n\r\n // Parsed markdown content\r\n content: string;\r\n\r\n // File metadata\r\n filePath: string;\r\n category?: string; // e.g., 'core-agents', 'specialized', 'custom'\r\n}\r\n\r\n/**\r\n * Parse YAML frontmatter from markdown content\r\n * Supports both Unix (LF) and Windows (CRLF) line endings\r\n */\r\nfunction parseFrontmatter(content: string): { frontmatter: Record<string, any>; body: string } {\r\n const frontmatterRegex = /^---\\r?\\n([\\s\\S]*?)\\r?\\n---\\r?\\n([\\s\\S]*)$/;\r\n const match = content.match(frontmatterRegex);\r\n\r\n if (!match) {\r\n return { frontmatter: {}, body: content };\r\n }\r\n\r\n const [, yamlContent, body] = match;\r\n\r\n \r\n // Simple YAML parser (handles basic key-value pairs, arrays, and objects)\r\n const frontmatter: Record<string, any> = {};\r\n const lines = yamlContent.split('\\n');\r\n let currentKey = '';\r\n let currentArray: string[] = [];\r\n let isInArray = false;\r\n let isInObject = false;\r\n let currentObject: Record<string, string> = {};\r\n let objectKey = '';\r\n\r\n for (const line of lines) {\r\n const trimmed = line.trim();\r\n if (!trimmed || trimmed.startsWith('#')) continue;\r\n\r\n // Array item\r\n if (trimmed.startsWith('- ')) {\r\n if (!isInArray) {\r\n isInArray = true;\r\n currentArray = [];\r\n }\r\n currentArray.push(trimmed.substring(2).trim());\r\n continue;\r\n }\r\n\r\n // End of array\r\n if (isInArray && !trimmed.startsWith('- ')) {\r\n frontmatter[currentKey] = currentArray;\r\n isInArray = false;\r\n currentArray = [];\r\n }\r\n\r\n // Object field (indented key-value)\r\n if (trimmed.match(/^\\s+\\w+:/) && isInObject) {\r\n const [objKey, ...objValueParts] = trimmed.split(':');\r\n const objValue = objValueParts.join(':').trim().replace(/^[\"']|[\"']$/g, '');\r\n currentObject[objKey.trim()] = objValue;\r\n continue;\r\n }\r\n\r\n // Key-value pair\r\n const colonIndex = trimmed.indexOf(':');\r\n if (colonIndex !== -1) {\r\n const key = trimmed.substring(0, colonIndex).trim();\r\n const value = trimmed.substring(colonIndex + 1).trim();\r\n\r\n // Check if this starts an object\r\n if (value === '') {\r\n isInObject = true;\r\n currentObject = {};\r\n objectKey = key;\r\n continue;\r\n }\r\n\r\n // End previous object if any\r\n if (isInObject && !trimmed.match(/^\\s+/)) {\r\n frontmatter[objectKey] = currentObject;\r\n isInObject = false;\r\n currentObject = {};\r\n }\r\n\r\n currentKey = key;\r\n\r\n // Multi-line string (starts with |)\r\n if (value === '|') {\r\n continue; // Will be handled by next lines\r\n }\r\n\r\n // Inline array (e.g., [item1, item2, item3])\r\n if (value.startsWith('[') && value.endsWith(']')) {\r\n const arrayContent = value.substring(1, value.length - 1);\r\n const items = arrayContent.split(',').map(item => item.trim());\r\n frontmatter[key] = items;\r\n continue;\r\n }\r\n\r\n // Remove quotes\r\n const cleanValue = value.replace(/^[\"']|[\"']$/g, '');\r\n frontmatter[key] = cleanValue;\r\n } else if (currentKey && trimmed && !isInArray && !isInObject) {\r\n // Continuation of multi-line string\r\n const existingValue = frontmatter[currentKey];\r\n frontmatter[currentKey] = existingValue\r\n ? `${existingValue}\\n${trimmed}`\r\n : trimmed;\r\n }\r\n }\r\n\r\n // Handle trailing array or object\r\n if (isInArray) {\r\n frontmatter[currentKey] = currentArray;\r\n }\r\n if (isInObject) {\r\n frontmatter[objectKey] = currentObject;\r\n }\r\n\r\n return { frontmatter, body: body.trim() };\r\n}\r\n\r\n/**\r\n * Find agent definition file by agent type/name\r\n * Searches multiple locations for agent definitions\r\n */\r\nasync function findAgentFile(agentType: string, baseDir: string = '.claude/agents'): Promise<string | null> {\r\n // Normalize agent type (handle both kebab-case and underscores)\r\n const normalizedType = agentType.toLowerCase().replace(/_/g, '-');\r\n\r\n // Search locations (in order of priority)\r\n const searchLocations = [\r\n baseDir, // Current working directory\r\n '.claude/agents', // Standard location\r\n path.join(__dirname, '../../.claude/agents'), // CLI installation directory\r\n '/app/.claude/agents', // Docker container location\r\n ];\r\n\r\n // Search patterns (in order of priority)\r\n const searchPatterns = [\r\n // Exact match in any subdirectory\r\n (loc: string) => `${loc}/**/${normalizedType}.md`,\r\n // Match with different casing\r\n (loc: string) => `${loc}/**/*${normalizedType}*.md`,\r\n ];\r\n\r\n for (const location of searchLocations) {\r\n for (const patternFn of searchPatterns) {\r\n const pattern = patternFn(location);\r\n try {\r\n const files = await glob(pattern, { nodir: true, absolute: true });\r\n if (files.length > 0) {\r\n // Prefer exact match over partial match\r\n const exactMatch = files.find(f => {\r\n const basename = path.basename(f, '.md').toLowerCase();\r\n return basename === normalizedType;\r\n });\r\n return exactMatch || files[0];\r\n }\r\n } catch (error) {\r\n // Skip location if it doesn't exist\r\n continue;\r\n }\r\n }\r\n }\r\n\r\n return null;\r\n}\r\n\r\n/**\r\n * Parse agent definition from file\r\n */\r\nexport async function parseAgentDefinition(agentType: string): Promise<AgentDefinition> {\r\n // Find agent file\r\n const filePath = await findAgentFile(agentType);\r\n\r\n if (!filePath) {\r\n throw new Error(`Agent definition not found: ${agentType}`);\r\n }\r\n\r\n // Read file content\r\n const content = await fs.readFile(filePath, 'utf-8');\r\n\r\n \r\n // Parse frontmatter and body\r\n const { frontmatter, body } = parseFrontmatter(content);\r\n\r\n // Extract category from path\r\n const relativePath = path.relative('.claude/agents', filePath);\r\n const category = relativePath.includes('/')\r\n ? relativePath.split('/')[0]\r\n : undefined;\r\n\r\n \r\n // Build agent definition\r\n const definition: AgentDefinition = {\r\n name: frontmatter.name || agentType,\r\n description: frontmatter.description || '',\r\n tools: Array.isArray(frontmatter.tools) ? frontmatter.tools : [],\r\n model: frontmatter.model || 'haiku',\r\n type: frontmatter.type,\r\n color: frontmatter.color,\r\n acl_level: frontmatter.acl_level ? parseInt(String(frontmatter.acl_level), 10) : undefined,\r\n capabilities: frontmatter.capabilities,\r\n validation_hooks: frontmatter.validation_hooks,\r\n lifecycle: frontmatter.lifecycle,\r\n content: body,\r\n filePath,\r\n category,\r\n };\r\n\r\n return definition;\r\n}\r\n\r\n/**\r\n * List all available agent definitions\r\n */\r\nexport async function listAgentDefinitions(baseDir: string = '.claude/agents'): Promise<string[]> {\r\n const pattern = `${baseDir}/**/*.md`;\r\n const files = await glob(pattern, { nodir: true });\r\n\r\n return files.map(f => path.basename(f, '.md'));\r\n}\r\n\r\n/**\r\n * Check if agent definition includes CFN Loop protocol\r\n */\r\nexport function hasCFNLoopProtocol(definition: AgentDefinition): boolean {\r\n const content = definition.content.toLowerCase();\r\n return (\r\n content.includes('cfn loop') &&\r\n content.includes('redis completion protocol') ||\r\n content.includes('invoke-waiting-mode.sh')\r\n );\r\n}\r\n"],"names":["fs","path","fileURLToPath","glob","__filename","url","__dirname","dirname","parseFrontmatter","content","frontmatterRegex","match","frontmatter","body","yamlContent","lines","split","currentKey","currentArray","isInArray","isInObject","currentObject","objectKey","line","trimmed","trim","startsWith","push","substring","objKey","objValueParts","objValue","join","replace","colonIndex","indexOf","key","value","endsWith","arrayContent","length","items","map","item","cleanValue","existingValue","findAgentFile","agentType","baseDir","normalizedType","toLowerCase","searchLocations","searchPatterns","loc","location","patternFn","pattern","files","nodir","absolute","exactMatch","find","f","basename","error","parseAgentDefinition","filePath","Error","readFile","relativePath","relative","category","includes","undefined","definition","name","description","tools","Array","isArray","model","type","color","acl_level","parseInt","String","capabilities","validation_hooks","lifecycle","listAgentDefinitions","hasCFNLoopProtocol"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/cli/agent-definition-parser.ts"],"sourcesContent":["/**\r\n * Agent Definition Parser\r\n *\r\n * Parses agent definition files (.md) with YAML frontmatter and markdown content.\r\n * Supports agent definitions in .claude/agents/ directory structure.\r\n */\r\n\r\nimport fs from 'fs/promises';\r\nimport path from 'path';\r\nimport { fileURLToPath } from 'url';\r\nimport { glob } from 'glob';\r\nimport { execSync } from 'child_process';\r\n\r\n// ES Module compatibility\r\nconst __filename = fileURLToPath(import.meta.url);\r\nconst __dirname = path.dirname(__filename);\r\n\r\n/**\r\n * Detect project root dynamically\r\n * Uses PROJECT_ROOT env var if set, otherwise tries git, falls back to cwd\r\n */\r\nfunction getProjectRoot(): string {\r\n // 1. Check environment variable\r\n if (process.env.PROJECT_ROOT) {\r\n return process.env.PROJECT_ROOT;\r\n }\r\n\r\n // 2. Try git rev-parse (most reliable)\r\n try {\r\n const gitRoot = execSync('git rev-parse --show-toplevel', {\r\n encoding: 'utf-8',\r\n cwd: process.cwd(),\r\n stdio: ['pipe', 'pipe', 'ignore']\r\n }).trim();\r\n if (gitRoot) {\r\n return gitRoot;\r\n }\r\n } catch {\r\n // Fall through to next method\r\n }\r\n\r\n // 3. Fall back to current working directory\r\n return process.cwd();\r\n}\r\n\r\nconst projectRoot = getProjectRoot();\r\n\r\nexport interface AgentDefinition {\r\n // YAML frontmatter fields\r\n name: string;\r\n description: string;\r\n tools: string[];\r\n model: 'haiku' | 'sonnet' | 'opus';\r\n type?: string;\r\n color?: string;\r\n acl_level?: number;\r\n capabilities?: string[];\r\n validation_hooks?: string[];\r\n lifecycle?: {\r\n pre_task?: string;\r\n post_task?: string;\r\n };\r\n\r\n // Parsed markdown content\r\n content: string;\r\n\r\n // File metadata\r\n filePath: string;\r\n category?: string; // e.g., 'core-agents', 'specialized', 'custom'\r\n}\r\n\r\n/**\r\n * Parse YAML frontmatter from markdown content\r\n * Supports both Unix (LF) and Windows (CRLF) line endings\r\n */\r\nfunction parseFrontmatter(content: string): { frontmatter: Record<string, any>; body: string } {\r\n const frontmatterRegex = /^---\\r?\\n([\\s\\S]*?)\\r?\\n---\\r?\\n([\\s\\S]*)$/;\r\n const match = content.match(frontmatterRegex);\r\n\r\n if (!match) {\r\n return { frontmatter: {}, body: content };\r\n }\r\n\r\n const [, yamlContent, body] = match;\r\n\r\n \r\n // Simple YAML parser (handles basic key-value pairs, arrays, and objects)\r\n const frontmatter: Record<string, any> = {};\r\n const lines = yamlContent.split('\\n');\r\n let currentKey = '';\r\n let currentArray: string[] = [];\r\n let isInArray = false;\r\n let isInObject = false;\r\n let currentObject: Record<string, string> = {};\r\n let objectKey = '';\r\n\r\n for (const line of lines) {\r\n const trimmed = line.trim();\r\n if (!trimmed || trimmed.startsWith('#')) continue;\r\n\r\n // Array item\r\n if (trimmed.startsWith('- ')) {\r\n if (!isInArray) {\r\n isInArray = true;\r\n currentArray = [];\r\n }\r\n currentArray.push(trimmed.substring(2).trim());\r\n continue;\r\n }\r\n\r\n // End of array\r\n if (isInArray && !trimmed.startsWith('- ')) {\r\n frontmatter[currentKey] = currentArray;\r\n isInArray = false;\r\n currentArray = [];\r\n }\r\n\r\n // Object field (indented key-value)\r\n if (trimmed.match(/^\\s+\\w+:/) && isInObject) {\r\n const [objKey, ...objValueParts] = trimmed.split(':');\r\n const objValue = objValueParts.join(':').trim().replace(/^[\"']|[\"']$/g, '');\r\n currentObject[objKey.trim()] = objValue;\r\n continue;\r\n }\r\n\r\n // Key-value pair\r\n const colonIndex = trimmed.indexOf(':');\r\n if (colonIndex !== -1) {\r\n const key = trimmed.substring(0, colonIndex).trim();\r\n const value = trimmed.substring(colonIndex + 1).trim();\r\n\r\n // Check if this starts an object\r\n if (value === '') {\r\n isInObject = true;\r\n currentObject = {};\r\n objectKey = key;\r\n continue;\r\n }\r\n\r\n // End previous object if any\r\n if (isInObject && !trimmed.match(/^\\s+/)) {\r\n frontmatter[objectKey] = currentObject;\r\n isInObject = false;\r\n currentObject = {};\r\n }\r\n\r\n currentKey = key;\r\n\r\n // Multi-line string (starts with |)\r\n if (value === '|') {\r\n continue; // Will be handled by next lines\r\n }\r\n\r\n // Inline array (e.g., [item1, item2, item3])\r\n if (value.startsWith('[') && value.endsWith(']')) {\r\n const arrayContent = value.substring(1, value.length - 1);\r\n const items = arrayContent.split(',').map(item => item.trim());\r\n frontmatter[key] = items;\r\n continue;\r\n }\r\n\r\n // Remove quotes\r\n const cleanValue = value.replace(/^[\"']|[\"']$/g, '');\r\n frontmatter[key] = cleanValue;\r\n } else if (currentKey && trimmed && !isInArray && !isInObject) {\r\n // Continuation of multi-line string\r\n const existingValue = frontmatter[currentKey];\r\n frontmatter[currentKey] = existingValue\r\n ? `${existingValue}\\n${trimmed}`\r\n : trimmed;\r\n }\r\n }\r\n\r\n // Handle trailing array or object\r\n if (isInArray) {\r\n frontmatter[currentKey] = currentArray;\r\n }\r\n if (isInObject) {\r\n frontmatter[objectKey] = currentObject;\r\n }\r\n\r\n return { frontmatter, body: body.trim() };\r\n}\r\n\r\n/**\r\n * Find agent definition file by agent type/name\r\n * Searches multiple locations for agent definitions\r\n */\r\nasync function findAgentFile(agentType: string, baseDir?: string): Promise<string | null> {\r\n // Normalize agent type (handle both kebab-case and underscores)\r\n const normalizedType = agentType.toLowerCase().replace(/_/g, '-');\r\n\r\n // Search locations (in order of priority)\r\n // Use provided baseDir, or construct default path from project root\r\n const defaultBaseDir = path.join(projectRoot, '.claude/agents');\r\n const searchLocations = [\r\n baseDir || defaultBaseDir, // Provided or default working directory\r\n defaultBaseDir, // Standard location relative to project root\r\n path.join(__dirname, '../../.claude/agents'), // CLI installation directory\r\n '/app/.claude/agents', // Docker container location\r\n ];\r\n\r\n // Search patterns (in order of priority)\r\n const searchPatterns = [\r\n // Exact match in any subdirectory\r\n (loc: string) => `${loc}/**/${normalizedType}.md`,\r\n // Match with different casing\r\n (loc: string) => `${loc}/**/*${normalizedType}*.md`,\r\n ];\r\n\r\n for (const location of searchLocations) {\r\n for (const patternFn of searchPatterns) {\r\n const pattern = patternFn(location);\r\n try {\r\n const files = await glob(pattern, { nodir: true, absolute: true });\r\n if (files.length > 0) {\r\n // Prefer exact match over partial match\r\n const exactMatch = files.find(f => {\r\n const basename = path.basename(f, '.md').toLowerCase();\r\n return basename === normalizedType;\r\n });\r\n return exactMatch || files[0];\r\n }\r\n } catch (error) {\r\n // Skip location if it doesn't exist\r\n continue;\r\n }\r\n }\r\n }\r\n\r\n return null;\r\n}\r\n\r\n/**\r\n * Parse agent definition from file\r\n */\r\nexport async function parseAgentDefinition(agentType: string): Promise<AgentDefinition> {\r\n // Find agent file\r\n const filePath = await findAgentFile(agentType);\r\n\r\n if (!filePath) {\r\n throw new Error(`Agent definition not found: ${agentType}`);\r\n }\r\n\r\n // Read file content\r\n const content = await fs.readFile(filePath, 'utf-8');\r\n\r\n \r\n // Parse frontmatter and body\r\n const { frontmatter, body } = parseFrontmatter(content);\r\n\r\n // Extract category from path\r\n const agentsPath = path.join(projectRoot, '.claude/agents');\r\n const relativePath = path.relative(agentsPath, filePath);\r\n const category = relativePath.includes('/')\r\n ? relativePath.split('/')[0]\r\n : undefined;\r\n\r\n \r\n // Build agent definition\r\n const definition: AgentDefinition = {\r\n name: frontmatter.name || agentType,\r\n description: frontmatter.description || '',\r\n tools: Array.isArray(frontmatter.tools) ? frontmatter.tools : [],\r\n model: frontmatter.model || 'haiku',\r\n type: frontmatter.type,\r\n color: frontmatter.color,\r\n acl_level: frontmatter.acl_level ? parseInt(String(frontmatter.acl_level), 10) : undefined,\r\n capabilities: frontmatter.capabilities,\r\n validation_hooks: frontmatter.validation_hooks,\r\n lifecycle: frontmatter.lifecycle,\r\n content: body,\r\n filePath,\r\n category,\r\n };\r\n\r\n return definition;\r\n}\r\n\r\n/**\r\n * List all available agent definitions\r\n */\r\nexport async function listAgentDefinitions(baseDir: string = '.claude/agents'): Promise<string[]> {\r\n const pattern = `${baseDir}/**/*.md`;\r\n const files = await glob(pattern, { nodir: true });\r\n\r\n return files.map(f => path.basename(f, '.md'));\r\n}\r\n\r\n/**\r\n * Check if agent definition includes CFN Loop protocol\r\n */\r\nexport function hasCFNLoopProtocol(definition: AgentDefinition): boolean {\r\n const content = definition.content.toLowerCase();\r\n return (\r\n content.includes('cfn loop') &&\r\n content.includes('redis completion protocol') ||\r\n content.includes('invoke-waiting-mode.sh')\r\n );\r\n}\r\n"],"names":["fs","path","fileURLToPath","glob","execSync","__filename","url","__dirname","dirname","getProjectRoot","process","env","PROJECT_ROOT","gitRoot","encoding","cwd","stdio","trim","projectRoot","parseFrontmatter","content","frontmatterRegex","match","frontmatter","body","yamlContent","lines","split","currentKey","currentArray","isInArray","isInObject","currentObject","objectKey","line","trimmed","startsWith","push","substring","objKey","objValueParts","objValue","join","replace","colonIndex","indexOf","key","value","endsWith","arrayContent","length","items","map","item","cleanValue","existingValue","findAgentFile","agentType","baseDir","normalizedType","toLowerCase","defaultBaseDir","searchLocations","searchPatterns","loc","location","patternFn","pattern","files","nodir","absolute","exactMatch","find","f","basename","error","parseAgentDefinition","filePath","Error","readFile","agentsPath","relativePath","relative","category","includes","undefined","definition","name","description","tools","Array","isArray","model","type","color","acl_level","parseInt","String","capabilities","validation_hooks","lifecycle","listAgentDefinitions","hasCFNLoopProtocol"],"mappings":"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"}
@@ -15,7 +15,37 @@ import { convertToolNames } from './tool-definitions.js';
15
15
  import fs from 'fs/promises';
16
16
  import path from 'path';
17
17
  import os from 'os';
18
+ import { execSync } from 'child_process';
18
19
  const execAsync = promisify(exec);
20
+ /**
21
+ * Detect project root dynamically
22
+ * Uses PROJECT_ROOT env var if set, otherwise tries git, falls back to cwd
23
+ */ function getProjectRoot() {
24
+ // 1. Check environment variable
25
+ if (process.env.PROJECT_ROOT) {
26
+ return process.env.PROJECT_ROOT;
27
+ }
28
+ // 2. Try git rev-parse (most reliable)
29
+ try {
30
+ const gitRoot = execSync('git rev-parse --show-toplevel', {
31
+ encoding: 'utf-8',
32
+ cwd: process.cwd(),
33
+ stdio: [
34
+ 'pipe',
35
+ 'pipe',
36
+ 'ignore'
37
+ ]
38
+ }).trim();
39
+ if (gitRoot) {
40
+ return gitRoot;
41
+ }
42
+ } catch {
43
+ // Fall through to next method
44
+ }
45
+ // 3. Fall back to current working directory
46
+ return process.cwd();
47
+ }
48
+ const projectRoot = getProjectRoot();
19
49
  // Bug #6 Fix: Read Redis connection parameters from process.env
20
50
  // ENV-001: Standardized environment variable naming (REDIS_PASSWORD for all deployments)
21
51
  const redisHost = process.env.CFN_REDIS_HOST || 'cfn-redis';
@@ -124,7 +154,7 @@ const redisPassword = process.env.CFN_REDIS_PASSWORD || process.env.REDIS_PASSWO
124
154
  }
125
155
  // Check config file (.claude/config/api-provider.json)
126
156
  try {
127
- const configPath = path.join('.claude', 'config', 'api-provider.json');
157
+ const configPath = path.join(projectRoot, '.claude', 'config', 'api-provider.json');
128
158
  const config = JSON.parse(await fs.readFile(configPath, 'utf-8'));
129
159
  return config.provider === 'zai' || config.provider === 'z.ai';
130
160
  } catch {
@@ -269,7 +299,7 @@ const redisPassword = process.env.CFN_REDIS_PASSWORD || process.env.REDIS_PASSWO
269
299
  console.log(`[agent-executor] Model: ${definition.model}`);
270
300
  console.log(`[agent-executor] Prompt file: ${promptFile}`);
271
301
  return new Promise((resolve)=>{
272
- const scriptPath = path.join('.claude', 'skills', 'agent-execution', 'execute-agent.sh');
302
+ const scriptPath = path.join(projectRoot, '.claude', 'skills', 'agent-execution', 'execute-agent.sh');
273
303
  // Build environment variables - WHITELIST ONLY APPROACH
274
304
  // SECURITY FIX: Do not use ...process.env spread which exposes ALL variables including secrets
275
305
  // Instead, explicitly whitelist safe variables to pass to spawned process
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/cli/agent-executor.ts"],"sourcesContent":["/**\r\n * Agent Executor\r\n *\r\n * Executes CLI-spawned agents by:\r\n * 1. Checking custom routing configuration (z.ai vs Anthropic)\r\n * 2. Invoking the appropriate API\r\n * 3. Managing agent lifecycle and output\r\n */\r\n\r\nimport { spawn } from 'child_process';\r\nimport { exec } from 'child_process';\r\nimport { promisify } from 'util';\r\nimport { AgentDefinition } from './agent-definition-parser.js';\r\nimport { TaskContext, getAgentId } from './agent-prompt-builder.js';\r\nimport { buildCLIAgentSystemPrompt, loadContextFromEnv } from './cli-agent-context.js';\r\nimport {\r\n loadMessages,\r\n storeMessage,\r\n getCurrentFork,\r\n formatMessagesForAPI,\r\n type Message\r\n} from './conversation-fork.js';\r\nimport { convertToolNames } from './tool-definitions.js';\r\nimport fs from 'fs/promises';\r\nimport path from 'path';\r\nimport os from 'os';\r\n\r\nconst execAsync = promisify(exec);\r\n\r\n// Bug #6 Fix: Read Redis connection parameters from process.env\r\n// ENV-001: Standardized environment variable naming (REDIS_PASSWORD for all deployments)\r\nconst redisHost = process.env.CFN_REDIS_HOST || 'cfn-redis';\r\nconst redisPort = process.env.CFN_REDIS_PORT || '6379';\r\nconst redisPassword = process.env.CFN_REDIS_PASSWORD || process.env.REDIS_PASSWORD || '';\r\n\r\nexport interface AgentExecutionResult {\r\n success: boolean;\r\n agentId: string;\r\n output?: string;\r\n error?: string;\r\n exitCode: number;\r\n}\r\n\r\n/**\r\n * Parse context string into environment variables\r\n *\r\n * Parses context string like \"TASK_ID='xyz' MODE='mvp' MAX_ITERATIONS=5\"\r\n * and sets the values as environment variables.\r\n *\r\n * Supports:\r\n * - Single quoted: KEY='value with spaces'\r\n * - Double quoted: KEY=\"value with spaces\"\r\n * - Unquoted: KEY=value (no spaces in value)\r\n *\r\n * @param contextString - Context string from --context parameter\r\n * @returns Object with parsed key-value pairs\r\n */\r\nfunction parseContextToEnv(contextString: string | undefined): Record<string, string> {\r\n if (!contextString) return {};\r\n\r\n const envVars: Record<string, string> = {};\r\n\r\n // Match KEY='value' or KEY=\"value\" or KEY=value patterns\r\n // For quoted values: capture everything between quotes\r\n // For unquoted values: capture until next space or end of string\r\n const regex = /(\\w+)=(?:(['\"])([^\\2]*?)\\2|([^\\s]+))/g;\r\n let match;\r\n\r\n while ((match = regex.exec(contextString)) !== null) {\r\n const [, key, , quotedValue, unquotedValue] = match;\r\n const value = quotedValue !== undefined ? quotedValue : unquotedValue;\r\n envVars[key] = value;\r\n // Also set in process.env for current process\r\n process.env[key] = value;\r\n }\r\n\r\n return envVars;\r\n}\r\n\r\n/**\r\n * Extract confidence score from agent output\r\n * Looks for patterns like:\r\n * - \"confidence: 0.85\"\r\n * - \"Confidence: 0.90\"\r\n * - \"confidence score: 0.95\"\r\n * - \"self-confidence: 0.88\"\r\n */\r\nfunction extractConfidence(output: string | undefined): number {\r\n if (!output) return 0.85;\r\n\r\n // Try multiple patterns\r\n const patterns = [\r\n /confidence:\\s*([0-9.]+)/i,\r\n /confidence\\s+score:\\s*([0-9.]+)/i,\r\n /self-confidence:\\s*([0-9.]+)/i,\r\n /my\\s+confidence:\\s*([0-9.]+)/i,\r\n ];\r\n\r\n for (const pattern of patterns) {\r\n const match = output.match(pattern);\r\n if (match && match[1]) {\r\n const score = parseFloat(match[1]);\r\n if (score >= 0 && score <= 1) {\r\n return score;\r\n }\r\n }\r\n }\r\n\r\n // Default to 0.85 if not found\r\n return 0.85;\r\n}\r\n\r\n/**\r\n * Execute CFN Loop protocol after agent completes work\r\n *\r\n * Steps:\r\n * 1. Signal completion to orchestrator\r\n * 2. Report confidence score\r\n * 3. Enter waiting mode (if iterations enabled)\r\n */\r\nasync function executeCFNProtocol(\r\n taskId: string,\r\n agentId: string,\r\n output: string | undefined,\r\n iteration: number,\r\n enableIterations: boolean = false,\r\n maxIterations: number = 10\r\n): Promise<void> {\r\n console.log(`\\n[CFN Protocol] Starting for agent ${agentId}`);\r\n console.log(`[CFN Protocol] Task ID: ${taskId}, Iteration: ${iteration}`);\r\n\r\n try {\r\n // Step 1: Signal completion\r\n console.log('[CFN Protocol] Step 1: Signaling completion...');\r\n const authFlag = redisPassword ? `-a \"${redisPassword}\"` : '';\r\n await execAsync(`redis-cli -h \"${redisHost}\" -p \"${redisPort}\" ${authFlag} lpush \"swarm:${taskId}:${agentId}:done\" \"complete\"`);\r\n console.log('[CFN Protocol] ✓ Completion signaled');\r\n\r\n // Step 2: Extract and report confidence\r\n const confidence = extractConfidence(output);\r\n console.log(`[CFN Protocol] Step 2: Reporting confidence (${confidence})...`);\r\n\r\n const reportCmd = `./.claude/skills/cfn-redis-coordination/report-completion.sh \\\r\n --task-id \"${taskId}\" \\\r\n --agent-id \"${agentId}\" \\\r\n --confidence ${confidence} \\\r\n --iteration ${iteration}`;\r\n\r\n await execAsync(reportCmd);\r\n console.log('[CFN Protocol] ✓ Confidence reported');\r\n\r\n // Step 3: Exit cleanly (BUG #18 FIX - removed waiting mode)\r\n // Orchestrator will spawn appropriate specialist agent for next iteration\r\n // This enables adaptive agent specialization based on feedback type\r\n console.log('[CFN Protocol] Step 3: Exiting cleanly (iteration complete)');\r\n console.log('[CFN Protocol] Protocol complete\\n');\r\n } catch (error) {\r\n console.error('[CFN Protocol] Error:', error);\r\n throw error;\r\n }\r\n}\r\n\r\n/**\r\n * Check if custom routing (z.ai) is enabled\r\n */\r\nasync function isCustomRoutingEnabled(): Promise<boolean> {\r\n // Check environment variable\r\n if (process.env.CLAUDE_API_PROVIDER === 'zai') {\r\n return true;\r\n }\r\n\r\n // Check config file (.claude/config/api-provider.json)\r\n try {\r\n const configPath = path.join('.claude', 'config', 'api-provider.json');\r\n const config = JSON.parse(await fs.readFile(configPath, 'utf-8'));\r\n return config.provider === 'zai' || config.provider === 'z.ai';\r\n } catch {\r\n return false;\r\n }\r\n}\r\n\r\n/**\r\n * Get API provider configuration\r\n */\r\nasync function getAPIProvider(): Promise<'anthropic' | 'zai'> {\r\n const customEnabled = await isCustomRoutingEnabled();\r\n return customEnabled ? 'zai' : 'anthropic';\r\n}\r\n\r\n/**\r\n * Execute agent using direct API calls\r\n */\r\nasync function executeViaAPI(\r\n definition: AgentDefinition,\r\n prompt: string,\r\n context: TaskContext\r\n): Promise<AgentExecutionResult> {\r\n const agentId = getAgentId(definition, context);\r\n\r\n console.log(`[agent-executor] Executing agent via API: ${definition.name}`);\r\n console.log(`[agent-executor] Agent ID: ${agentId}`);\r\n console.log(`[agent-executor] Model: ${definition.model}`);\r\n console.log('');\r\n\r\n // BUG #24 FIX: Parse and inject context environment variables\r\n // This enables CLI-spawned agents to access TASK_ID, MODE, etc. in Bash tool\r\n if (context.context) {\r\n console.log(`[agent-executor] Parsing context: ${context.context}`);\r\n const contextEnv = parseContextToEnv(context.context);\r\n console.log(`[agent-executor] Injected env vars: ${Object.keys(contextEnv).join(', ')}`);\r\n }\r\n\r\n try {\r\n // Check for conversation fork (Sprint 4 enhancement)\r\n const forkId = process.env.FORK_ID || await getCurrentFork(context.taskId || '', agentId);\r\n const iteration = context.iteration || 1;\r\n\r\n let systemPrompt: string;\r\n let messages: Array<{role: string, content: string}> = [];\r\n\r\n if (forkId && iteration > 1) {\r\n // Continue from fork (iterations 2+)\r\n console.log(`[agent-executor] Continuing from fork: ${forkId}`);\r\n\r\n // Load fork messages\r\n const forkMessages = await loadMessages(context.taskId || '', agentId, forkId);\r\n console.log(`[agent-executor] Loaded ${forkMessages.length} messages from fork`);\r\n\r\n // Extract system prompt from first message (it's always the system message)\r\n // The fork messages are assistant/user pairs, we need to add system separately\r\n systemPrompt = forkMessages[0]?.content || '';\r\n\r\n // Format remaining messages for API\r\n messages = formatMessagesForAPI(forkMessages.slice(1));\r\n\r\n // Add new user message with feedback\r\n messages.push({\r\n role: 'user',\r\n content: prompt\r\n });\r\n\r\n console.log(`[agent-executor] Fork continuation: ${messages.length} messages`);\r\n } else {\r\n // New conversation (iteration 1)\r\n console.log('[agent-executor] Starting new conversation');\r\n console.log('[agent-executor] Building system prompt with context...');\r\n\r\n const contextOptions = loadContextFromEnv();\r\n contextOptions.agentType = definition.name;\r\n if (context.taskId) contextOptions.taskId = context.taskId;\r\n if (context.iteration) contextOptions.iteration = context.iteration;\r\n\r\n systemPrompt = await buildCLIAgentSystemPrompt(contextOptions);\r\n console.log('[agent-executor] System prompt built successfully');\r\n\r\n // Initial user message\r\n messages = [{\r\n role: 'user',\r\n content: prompt\r\n }];\r\n }\r\n\r\n console.log('');\r\n\r\n // Dynamic import to avoid bundling issues\r\n const { executeAgentAPI } = await import('./anthropic-client.js');\r\n\r\n // Convert agent tool names to Anthropic API format\r\n const tools = definition.tools && definition.tools.length > 0\r\n ? convertToolNames(definition.tools)\r\n : undefined;\r\n\r\n const result = await executeAgentAPI(\r\n definition.name,\r\n agentId,\r\n definition.model,\r\n prompt,\r\n systemPrompt,\r\n messages.length > 1 ? messages : undefined,\r\n undefined, // maxTokens (use default)\r\n tools // Pass converted tools\r\n );\r\n\r\n // Store messages in conversation history (for future forking)\r\n if (context.taskId) {\r\n // Store user message\r\n const userMessage: Message = {\r\n role: 'user',\r\n content: prompt,\r\n iteration,\r\n timestamp: new Date().toISOString()\r\n };\r\n await storeMessage(context.taskId, agentId, userMessage);\r\n\r\n // Store assistant response\r\n if (result.output) {\r\n const assistantMessage: Message = {\r\n role: 'assistant',\r\n content: result.output,\r\n iteration,\r\n timestamp: new Date().toISOString()\r\n };\r\n await storeMessage(context.taskId, agentId, assistantMessage);\r\n }\r\n\r\n console.log(`[agent-executor] Stored messages for iteration ${iteration}`);\r\n\r\n // Execute CFN Loop protocol (signal completion, report confidence, enter waiting mode)\r\n // Iterations are enabled for CFN Loop tasks (indicated by presence of taskId)\r\n try {\r\n const maxIterations = 10; // Default max iterations\r\n const enableIterations = true; // Enable iterations for all CFN Loop tasks\r\n\r\n await executeCFNProtocol(\r\n context.taskId,\r\n agentId,\r\n result.output,\r\n iteration,\r\n enableIterations,\r\n maxIterations\r\n );\r\n } catch (error) {\r\n console.error('[agent-executor] CFN Protocol execution failed:', error);\r\n // Don't fail the entire agent execution if CFN protocol fails\r\n // This allows agents to complete even if Redis coordination has issues\r\n }\r\n }\r\n\r\n return {\r\n success: result.success,\r\n agentId,\r\n output: result.output,\r\n error: result.error,\r\n exitCode: result.success ? 0 : 1,\r\n };\r\n } catch (error) {\r\n console.error('[agent-executor] API execution failed:', error);\r\n return {\r\n success: false,\r\n agentId,\r\n error: error instanceof Error ? error.message : String(error),\r\n exitCode: 1,\r\n };\r\n }\r\n}\r\n\r\n/**\r\n * Execute agent using shell script (fallback/simulation)\r\n */\r\nasync function executeViaScript(\r\n definition: AgentDefinition,\r\n prompt: string,\r\n context: TaskContext\r\n): Promise<AgentExecutionResult> {\r\n const agentId = getAgentId(definition, context);\r\n\r\n // BUG #24 FIX: Parse and inject context environment variables\r\n if (context.context) {\r\n console.log(`[agent-executor] Parsing context: ${context.context}`);\r\n const contextEnv = parseContextToEnv(context.context);\r\n console.log(`[agent-executor] Injected env vars: ${Object.keys(contextEnv).join(', ')}`);\r\n }\r\n\r\n // Write prompt to temporary file\r\n const tmpDir = os.tmpdir();\r\n const promptFile = path.join(tmpDir, `agent-${agentId}-${Date.now()}.md`);\r\n await fs.writeFile(promptFile, prompt, 'utf-8');\r\n\r\n console.log(`[agent-executor] Executing agent via script: ${definition.name}`);\r\n console.log(`[agent-executor] Agent ID: ${agentId}`);\r\n console.log(`[agent-executor] Model: ${definition.model}`);\r\n console.log(`[agent-executor] Prompt file: ${promptFile}`);\r\n\r\n return new Promise((resolve) => {\r\n const scriptPath = path.join('.claude', 'skills', 'agent-execution', 'execute-agent.sh');\r\n\r\n // Build environment variables - WHITELIST ONLY APPROACH\r\n // SECURITY FIX: Do not use ...process.env spread which exposes ALL variables including secrets\r\n // Instead, explicitly whitelist safe variables to pass to spawned process\r\n const safeEnvVars = [\r\n 'CFN_REDIS_HOST',\r\n 'CFN_REDIS_PORT',\r\n 'CFN_REDIS_PASSWORD', // CRITICAL: Required for Redis authentication\r\n 'CFN_REDIS_URL',\r\n 'REDIS_PASSWORD', // Fallback for Redis password\r\n 'CFN_MEMORY_BUDGET',\r\n 'CFN_API_HOST',\r\n 'CFN_API_PORT',\r\n 'CFN_LOG_LEVEL',\r\n 'CFN_LOG_FORMAT',\r\n 'CFN_CONTAINER_MODE',\r\n 'CFN_DOCKER_SOCKET',\r\n 'CFN_NETWORK_NAME',\r\n 'CFN_CUSTOM_ROUTING',\r\n 'CFN_DEFAULT_PROVIDER',\r\n 'NODE_ENV',\r\n 'PATH',\r\n 'HOME',\r\n 'PWD' // Required for working directory context\r\n ];\r\n\r\n const env: Record<string, string> = {};\r\n\r\n // Add whitelisted variables\r\n for (const key of safeEnvVars) {\r\n const value = process.env[key];\r\n if (value !== undefined) {\r\n env[key] = value;\r\n }\r\n }\r\n\r\n // Add API key only when explicitly needed (with strict validation)\r\n if (process.env.ANTHROPIC_API_KEY) {\r\n if (process.env.ANTHROPIC_API_KEY.match(/^sk-[a-zA-Z0-9-]+$/)) {\r\n env.ANTHROPIC_API_KEY = process.env.ANTHROPIC_API_KEY;\r\n }\r\n }\r\n\r\n // Add agent execution context (safe values)\r\n env.AGENT_TYPE = definition.name;\r\n env.AGENT_ID = agentId;\r\n env.AGENT_MODEL = definition.model;\r\n env.AGENT_TOOLS = definition.tools.join(',');\r\n env.TASK_ID = context.taskId || '';\r\n env.ITERATION = String(context.iteration || 1);\r\n env.MODE = context.mode || 'cli';\r\n env.PROMPT_FILE = promptFile;\r\n\r\n // Check if execute script exists\r\n fs.access(scriptPath)\r\n .then(() => {\r\n // Use execution script\r\n const proc = spawn('bash', [scriptPath], { env, stdio: 'inherit' });\r\n\r\n proc.on('exit', (code) => {\r\n resolve({\r\n success: code === 0,\r\n agentId,\r\n exitCode: code || 0,\r\n });\r\n });\r\n\r\n proc.on('error', (err) => {\r\n resolve({\r\n success: false,\r\n agentId,\r\n error: err.message,\r\n exitCode: 1,\r\n });\r\n });\r\n })\r\n .catch(() => {\r\n // Fallback: Print prompt\r\n console.log('\\n=== Agent Prompt ===');\r\n console.log(prompt.substring(0, 500) + '...');\r\n console.log('\\n[agent-executor] Execution script not found');\r\n console.log('[agent-executor] Using simulation mode\\n');\r\n\r\n resolve({\r\n success: true,\r\n agentId,\r\n output: prompt,\r\n exitCode: 0,\r\n });\r\n });\r\n });\r\n}\r\n\r\n/**\r\n * Main agent execution function\r\n */\r\nexport async function executeAgent(\r\n definition: AgentDefinition,\r\n prompt: string,\r\n context: TaskContext,\r\n options: {\r\n method?: 'auto' | 'api' | 'script';\r\n } = {}\r\n): Promise<AgentExecutionResult> {\r\n const method = options.method || 'auto';\r\n\r\n // Auto-select execution method\r\n if (method === 'auto') {\r\n // Try API execution first, fallback to script if API key not available\r\n try {\r\n return await executeViaAPI(definition, prompt, context);\r\n } catch (error) {\r\n if (error instanceof Error && error.message.includes('API key not found')) {\r\n console.log('[agent-executor] API key not found, using script fallback');\r\n return executeViaScript(definition, prompt, context);\r\n }\r\n throw error;\r\n }\r\n }\r\n\r\n if (method === 'api') {\r\n return executeViaAPI(definition, prompt, context);\r\n }\r\n\r\n return executeViaScript(definition, prompt, context);\r\n}\r\n\r\n/**\r\n * Write agent output to file for debugging\r\n */\r\nexport async function saveAgentOutput(\r\n agentId: string,\r\n output: string,\r\n outputDir: string = '.claude/tmp/agent-output'\r\n): Promise<string> {\r\n await fs.mkdir(outputDir, { recursive: true });\r\n\r\n const timestamp = new Date().toISOString().replace(/[:.]/g, '-');\r\n const filename = `${agentId}-${timestamp}.txt`;\r\n const filepath = path.join(outputDir, filename);\r\n\r\n await fs.writeFile(filepath, output, 'utf-8');\r\n\r\n return filepath;\r\n}\r\n"],"names":["spawn","exec","promisify","getAgentId","buildCLIAgentSystemPrompt","loadContextFromEnv","loadMessages","storeMessage","getCurrentFork","formatMessagesForAPI","convertToolNames","fs","path","os","execAsync","redisHost","process","env","CFN_REDIS_HOST","redisPort","CFN_REDIS_PORT","redisPassword","CFN_REDIS_PASSWORD","REDIS_PASSWORD","parseContextToEnv","contextString","envVars","regex","match","key","quotedValue","unquotedValue","value","undefined","extractConfidence","output","patterns","pattern","score","parseFloat","executeCFNProtocol","taskId","agentId","iteration","enableIterations","maxIterations","console","log","authFlag","confidence","reportCmd","error","isCustomRoutingEnabled","CLAUDE_API_PROVIDER","configPath","join","config","JSON","parse","readFile","provider","getAPIProvider","customEnabled","executeViaAPI","definition","prompt","context","name","model","contextEnv","Object","keys","forkId","FORK_ID","systemPrompt","messages","forkMessages","length","content","slice","push","role","contextOptions","agentType","executeAgentAPI","tools","result","userMessage","timestamp","Date","toISOString","assistantMessage","success","exitCode","Error","message","String","executeViaScript","tmpDir","tmpdir","promptFile","now","writeFile","Promise","resolve","scriptPath","safeEnvVars","ANTHROPIC_API_KEY","AGENT_TYPE","AGENT_ID","AGENT_MODEL","AGENT_TOOLS","TASK_ID","ITERATION","MODE","mode","PROMPT_FILE","access","then","proc","stdio","on","code","err","catch","substring","executeAgent","options","method","includes","saveAgentOutput","outputDir","mkdir","recursive","replace","filename","filepath"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/cli/agent-executor.ts"],"sourcesContent":["/**\r\n * Agent Executor\r\n *\r\n * Executes CLI-spawned agents by:\r\n * 1. Checking custom routing configuration (z.ai vs Anthropic)\r\n * 2. Invoking the appropriate API\r\n * 3. Managing agent lifecycle and output\r\n */\r\n\r\nimport { spawn } from 'child_process';\r\nimport { exec } from 'child_process';\r\nimport { promisify } from 'util';\r\nimport { AgentDefinition } from './agent-definition-parser.js';\r\nimport { TaskContext, getAgentId } from './agent-prompt-builder.js';\r\nimport { buildCLIAgentSystemPrompt, loadContextFromEnv } from './cli-agent-context.js';\r\nimport {\r\n loadMessages,\r\n storeMessage,\r\n getCurrentFork,\r\n formatMessagesForAPI,\r\n type Message\r\n} from './conversation-fork.js';\r\nimport { convertToolNames } from './tool-definitions.js';\r\nimport fs from 'fs/promises';\r\nimport path from 'path';\r\nimport os from 'os';\r\nimport { execSync } from 'child_process';\r\n\r\nconst execAsync = promisify(exec);\r\n\r\n/**\r\n * Detect project root dynamically\r\n * Uses PROJECT_ROOT env var if set, otherwise tries git, falls back to cwd\r\n */\r\nfunction getProjectRoot(): string {\r\n // 1. Check environment variable\r\n if (process.env.PROJECT_ROOT) {\r\n return process.env.PROJECT_ROOT;\r\n }\r\n\r\n // 2. Try git rev-parse (most reliable)\r\n try {\r\n const gitRoot = execSync('git rev-parse --show-toplevel', {\r\n encoding: 'utf-8',\r\n cwd: process.cwd(),\r\n stdio: ['pipe', 'pipe', 'ignore']\r\n }).trim();\r\n if (gitRoot) {\r\n return gitRoot;\r\n }\r\n } catch {\r\n // Fall through to next method\r\n }\r\n\r\n // 3. Fall back to current working directory\r\n return process.cwd();\r\n}\r\n\r\nconst projectRoot = getProjectRoot();\r\n\r\n// Bug #6 Fix: Read Redis connection parameters from process.env\r\n// ENV-001: Standardized environment variable naming (REDIS_PASSWORD for all deployments)\r\nconst redisHost = process.env.CFN_REDIS_HOST || 'cfn-redis';\r\nconst redisPort = process.env.CFN_REDIS_PORT || '6379';\r\nconst redisPassword = process.env.CFN_REDIS_PASSWORD || process.env.REDIS_PASSWORD || '';\r\n\r\nexport interface AgentExecutionResult {\r\n success: boolean;\r\n agentId: string;\r\n output?: string;\r\n error?: string;\r\n exitCode: number;\r\n}\r\n\r\n/**\r\n * Parse context string into environment variables\r\n *\r\n * Parses context string like \"TASK_ID='xyz' MODE='mvp' MAX_ITERATIONS=5\"\r\n * and sets the values as environment variables.\r\n *\r\n * Supports:\r\n * - Single quoted: KEY='value with spaces'\r\n * - Double quoted: KEY=\"value with spaces\"\r\n * - Unquoted: KEY=value (no spaces in value)\r\n *\r\n * @param contextString - Context string from --context parameter\r\n * @returns Object with parsed key-value pairs\r\n */\r\nfunction parseContextToEnv(contextString: string | undefined): Record<string, string> {\r\n if (!contextString) return {};\r\n\r\n const envVars: Record<string, string> = {};\r\n\r\n // Match KEY='value' or KEY=\"value\" or KEY=value patterns\r\n // For quoted values: capture everything between quotes\r\n // For unquoted values: capture until next space or end of string\r\n const regex = /(\\w+)=(?:(['\"])([^\\2]*?)\\2|([^\\s]+))/g;\r\n let match;\r\n\r\n while ((match = regex.exec(contextString)) !== null) {\r\n const [, key, , quotedValue, unquotedValue] = match;\r\n const value = quotedValue !== undefined ? quotedValue : unquotedValue;\r\n envVars[key] = value;\r\n // Also set in process.env for current process\r\n process.env[key] = value;\r\n }\r\n\r\n return envVars;\r\n}\r\n\r\n/**\r\n * Extract confidence score from agent output\r\n * Looks for patterns like:\r\n * - \"confidence: 0.85\"\r\n * - \"Confidence: 0.90\"\r\n * - \"confidence score: 0.95\"\r\n * - \"self-confidence: 0.88\"\r\n */\r\nfunction extractConfidence(output: string | undefined): number {\r\n if (!output) return 0.85;\r\n\r\n // Try multiple patterns\r\n const patterns = [\r\n /confidence:\\s*([0-9.]+)/i,\r\n /confidence\\s+score:\\s*([0-9.]+)/i,\r\n /self-confidence:\\s*([0-9.]+)/i,\r\n /my\\s+confidence:\\s*([0-9.]+)/i,\r\n ];\r\n\r\n for (const pattern of patterns) {\r\n const match = output.match(pattern);\r\n if (match && match[1]) {\r\n const score = parseFloat(match[1]);\r\n if (score >= 0 && score <= 1) {\r\n return score;\r\n }\r\n }\r\n }\r\n\r\n // Default to 0.85 if not found\r\n return 0.85;\r\n}\r\n\r\n/**\r\n * Execute CFN Loop protocol after agent completes work\r\n *\r\n * Steps:\r\n * 1. Signal completion to orchestrator\r\n * 2. Report confidence score\r\n * 3. Enter waiting mode (if iterations enabled)\r\n */\r\nasync function executeCFNProtocol(\r\n taskId: string,\r\n agentId: string,\r\n output: string | undefined,\r\n iteration: number,\r\n enableIterations: boolean = false,\r\n maxIterations: number = 10\r\n): Promise<void> {\r\n console.log(`\\n[CFN Protocol] Starting for agent ${agentId}`);\r\n console.log(`[CFN Protocol] Task ID: ${taskId}, Iteration: ${iteration}`);\r\n\r\n try {\r\n // Step 1: Signal completion\r\n console.log('[CFN Protocol] Step 1: Signaling completion...');\r\n const authFlag = redisPassword ? `-a \"${redisPassword}\"` : '';\r\n await execAsync(`redis-cli -h \"${redisHost}\" -p \"${redisPort}\" ${authFlag} lpush \"swarm:${taskId}:${agentId}:done\" \"complete\"`);\r\n console.log('[CFN Protocol] ✓ Completion signaled');\r\n\r\n // Step 2: Extract and report confidence\r\n const confidence = extractConfidence(output);\r\n console.log(`[CFN Protocol] Step 2: Reporting confidence (${confidence})...`);\r\n\r\n const reportCmd = `./.claude/skills/cfn-redis-coordination/report-completion.sh \\\r\n --task-id \"${taskId}\" \\\r\n --agent-id \"${agentId}\" \\\r\n --confidence ${confidence} \\\r\n --iteration ${iteration}`;\r\n\r\n await execAsync(reportCmd);\r\n console.log('[CFN Protocol] ✓ Confidence reported');\r\n\r\n // Step 3: Exit cleanly (BUG #18 FIX - removed waiting mode)\r\n // Orchestrator will spawn appropriate specialist agent for next iteration\r\n // This enables adaptive agent specialization based on feedback type\r\n console.log('[CFN Protocol] Step 3: Exiting cleanly (iteration complete)');\r\n console.log('[CFN Protocol] Protocol complete\\n');\r\n } catch (error) {\r\n console.error('[CFN Protocol] Error:', error);\r\n throw error;\r\n }\r\n}\r\n\r\n/**\r\n * Check if custom routing (z.ai) is enabled\r\n */\r\nasync function isCustomRoutingEnabled(): Promise<boolean> {\r\n // Check environment variable\r\n if (process.env.CLAUDE_API_PROVIDER === 'zai') {\r\n return true;\r\n }\r\n\r\n // Check config file (.claude/config/api-provider.json)\r\n try {\r\n const configPath = path.join(projectRoot, '.claude', 'config', 'api-provider.json');\r\n const config = JSON.parse(await fs.readFile(configPath, 'utf-8'));\r\n return config.provider === 'zai' || config.provider === 'z.ai';\r\n } catch {\r\n return false;\r\n }\r\n}\r\n\r\n/**\r\n * Get API provider configuration\r\n */\r\nasync function getAPIProvider(): Promise<'anthropic' | 'zai'> {\r\n const customEnabled = await isCustomRoutingEnabled();\r\n return customEnabled ? 'zai' : 'anthropic';\r\n}\r\n\r\n/**\r\n * Execute agent using direct API calls\r\n */\r\nasync function executeViaAPI(\r\n definition: AgentDefinition,\r\n prompt: string,\r\n context: TaskContext\r\n): Promise<AgentExecutionResult> {\r\n const agentId = getAgentId(definition, context);\r\n\r\n console.log(`[agent-executor] Executing agent via API: ${definition.name}`);\r\n console.log(`[agent-executor] Agent ID: ${agentId}`);\r\n console.log(`[agent-executor] Model: ${definition.model}`);\r\n console.log('');\r\n\r\n // BUG #24 FIX: Parse and inject context environment variables\r\n // This enables CLI-spawned agents to access TASK_ID, MODE, etc. in Bash tool\r\n if (context.context) {\r\n console.log(`[agent-executor] Parsing context: ${context.context}`);\r\n const contextEnv = parseContextToEnv(context.context);\r\n console.log(`[agent-executor] Injected env vars: ${Object.keys(contextEnv).join(', ')}`);\r\n }\r\n\r\n try {\r\n // Check for conversation fork (Sprint 4 enhancement)\r\n const forkId = process.env.FORK_ID || await getCurrentFork(context.taskId || '', agentId);\r\n const iteration = context.iteration || 1;\r\n\r\n let systemPrompt: string;\r\n let messages: Array<{role: string, content: string}> = [];\r\n\r\n if (forkId && iteration > 1) {\r\n // Continue from fork (iterations 2+)\r\n console.log(`[agent-executor] Continuing from fork: ${forkId}`);\r\n\r\n // Load fork messages\r\n const forkMessages = await loadMessages(context.taskId || '', agentId, forkId);\r\n console.log(`[agent-executor] Loaded ${forkMessages.length} messages from fork`);\r\n\r\n // Extract system prompt from first message (it's always the system message)\r\n // The fork messages are assistant/user pairs, we need to add system separately\r\n systemPrompt = forkMessages[0]?.content || '';\r\n\r\n // Format remaining messages for API\r\n messages = formatMessagesForAPI(forkMessages.slice(1));\r\n\r\n // Add new user message with feedback\r\n messages.push({\r\n role: 'user',\r\n content: prompt\r\n });\r\n\r\n console.log(`[agent-executor] Fork continuation: ${messages.length} messages`);\r\n } else {\r\n // New conversation (iteration 1)\r\n console.log('[agent-executor] Starting new conversation');\r\n console.log('[agent-executor] Building system prompt with context...');\r\n\r\n const contextOptions = loadContextFromEnv();\r\n contextOptions.agentType = definition.name;\r\n if (context.taskId) contextOptions.taskId = context.taskId;\r\n if (context.iteration) contextOptions.iteration = context.iteration;\r\n\r\n systemPrompt = await buildCLIAgentSystemPrompt(contextOptions);\r\n console.log('[agent-executor] System prompt built successfully');\r\n\r\n // Initial user message\r\n messages = [{\r\n role: 'user',\r\n content: prompt\r\n }];\r\n }\r\n\r\n console.log('');\r\n\r\n // Dynamic import to avoid bundling issues\r\n const { executeAgentAPI } = await import('./anthropic-client.js');\r\n\r\n // Convert agent tool names to Anthropic API format\r\n const tools = definition.tools && definition.tools.length > 0\r\n ? convertToolNames(definition.tools)\r\n : undefined;\r\n\r\n const result = await executeAgentAPI(\r\n definition.name,\r\n agentId,\r\n definition.model,\r\n prompt,\r\n systemPrompt,\r\n messages.length > 1 ? messages : undefined,\r\n undefined, // maxTokens (use default)\r\n tools // Pass converted tools\r\n );\r\n\r\n // Store messages in conversation history (for future forking)\r\n if (context.taskId) {\r\n // Store user message\r\n const userMessage: Message = {\r\n role: 'user',\r\n content: prompt,\r\n iteration,\r\n timestamp: new Date().toISOString()\r\n };\r\n await storeMessage(context.taskId, agentId, userMessage);\r\n\r\n // Store assistant response\r\n if (result.output) {\r\n const assistantMessage: Message = {\r\n role: 'assistant',\r\n content: result.output,\r\n iteration,\r\n timestamp: new Date().toISOString()\r\n };\r\n await storeMessage(context.taskId, agentId, assistantMessage);\r\n }\r\n\r\n console.log(`[agent-executor] Stored messages for iteration ${iteration}`);\r\n\r\n // Execute CFN Loop protocol (signal completion, report confidence, enter waiting mode)\r\n // Iterations are enabled for CFN Loop tasks (indicated by presence of taskId)\r\n try {\r\n const maxIterations = 10; // Default max iterations\r\n const enableIterations = true; // Enable iterations for all CFN Loop tasks\r\n\r\n await executeCFNProtocol(\r\n context.taskId,\r\n agentId,\r\n result.output,\r\n iteration,\r\n enableIterations,\r\n maxIterations\r\n );\r\n } catch (error) {\r\n console.error('[agent-executor] CFN Protocol execution failed:', error);\r\n // Don't fail the entire agent execution if CFN protocol fails\r\n // This allows agents to complete even if Redis coordination has issues\r\n }\r\n }\r\n\r\n return {\r\n success: result.success,\r\n agentId,\r\n output: result.output,\r\n error: result.error,\r\n exitCode: result.success ? 0 : 1,\r\n };\r\n } catch (error) {\r\n console.error('[agent-executor] API execution failed:', error);\r\n return {\r\n success: false,\r\n agentId,\r\n error: error instanceof Error ? error.message : String(error),\r\n exitCode: 1,\r\n };\r\n }\r\n}\r\n\r\n/**\r\n * Execute agent using shell script (fallback/simulation)\r\n */\r\nasync function executeViaScript(\r\n definition: AgentDefinition,\r\n prompt: string,\r\n context: TaskContext\r\n): Promise<AgentExecutionResult> {\r\n const agentId = getAgentId(definition, context);\r\n\r\n // BUG #24 FIX: Parse and inject context environment variables\r\n if (context.context) {\r\n console.log(`[agent-executor] Parsing context: ${context.context}`);\r\n const contextEnv = parseContextToEnv(context.context);\r\n console.log(`[agent-executor] Injected env vars: ${Object.keys(contextEnv).join(', ')}`);\r\n }\r\n\r\n // Write prompt to temporary file\r\n const tmpDir = os.tmpdir();\r\n const promptFile = path.join(tmpDir, `agent-${agentId}-${Date.now()}.md`);\r\n await fs.writeFile(promptFile, prompt, 'utf-8');\r\n\r\n console.log(`[agent-executor] Executing agent via script: ${definition.name}`);\r\n console.log(`[agent-executor] Agent ID: ${agentId}`);\r\n console.log(`[agent-executor] Model: ${definition.model}`);\r\n console.log(`[agent-executor] Prompt file: ${promptFile}`);\r\n\r\n return new Promise((resolve) => {\r\n const scriptPath = path.join(projectRoot, '.claude', 'skills', 'agent-execution', 'execute-agent.sh');\r\n\r\n // Build environment variables - WHITELIST ONLY APPROACH\r\n // SECURITY FIX: Do not use ...process.env spread which exposes ALL variables including secrets\r\n // Instead, explicitly whitelist safe variables to pass to spawned process\r\n const safeEnvVars = [\r\n 'CFN_REDIS_HOST',\r\n 'CFN_REDIS_PORT',\r\n 'CFN_REDIS_PASSWORD', // CRITICAL: Required for Redis authentication\r\n 'CFN_REDIS_URL',\r\n 'REDIS_PASSWORD', // Fallback for Redis password\r\n 'CFN_MEMORY_BUDGET',\r\n 'CFN_API_HOST',\r\n 'CFN_API_PORT',\r\n 'CFN_LOG_LEVEL',\r\n 'CFN_LOG_FORMAT',\r\n 'CFN_CONTAINER_MODE',\r\n 'CFN_DOCKER_SOCKET',\r\n 'CFN_NETWORK_NAME',\r\n 'CFN_CUSTOM_ROUTING',\r\n 'CFN_DEFAULT_PROVIDER',\r\n 'NODE_ENV',\r\n 'PATH',\r\n 'HOME',\r\n 'PWD' // Required for working directory context\r\n ];\r\n\r\n const env: Record<string, string> = {};\r\n\r\n // Add whitelisted variables\r\n for (const key of safeEnvVars) {\r\n const value = process.env[key];\r\n if (value !== undefined) {\r\n env[key] = value;\r\n }\r\n }\r\n\r\n // Add API key only when explicitly needed (with strict validation)\r\n if (process.env.ANTHROPIC_API_KEY) {\r\n if (process.env.ANTHROPIC_API_KEY.match(/^sk-[a-zA-Z0-9-]+$/)) {\r\n env.ANTHROPIC_API_KEY = process.env.ANTHROPIC_API_KEY;\r\n }\r\n }\r\n\r\n // Add agent execution context (safe values)\r\n env.AGENT_TYPE = definition.name;\r\n env.AGENT_ID = agentId;\r\n env.AGENT_MODEL = definition.model;\r\n env.AGENT_TOOLS = definition.tools.join(',');\r\n env.TASK_ID = context.taskId || '';\r\n env.ITERATION = String(context.iteration || 1);\r\n env.MODE = context.mode || 'cli';\r\n env.PROMPT_FILE = promptFile;\r\n\r\n // Check if execute script exists\r\n fs.access(scriptPath)\r\n .then(() => {\r\n // Use execution script\r\n const proc = spawn('bash', [scriptPath], { env, stdio: 'inherit' });\r\n\r\n proc.on('exit', (code) => {\r\n resolve({\r\n success: code === 0,\r\n agentId,\r\n exitCode: code || 0,\r\n });\r\n });\r\n\r\n proc.on('error', (err) => {\r\n resolve({\r\n success: false,\r\n agentId,\r\n error: err.message,\r\n exitCode: 1,\r\n });\r\n });\r\n })\r\n .catch(() => {\r\n // Fallback: Print prompt\r\n console.log('\\n=== Agent Prompt ===');\r\n console.log(prompt.substring(0, 500) + '...');\r\n console.log('\\n[agent-executor] Execution script not found');\r\n console.log('[agent-executor] Using simulation mode\\n');\r\n\r\n resolve({\r\n success: true,\r\n agentId,\r\n output: prompt,\r\n exitCode: 0,\r\n });\r\n });\r\n });\r\n}\r\n\r\n/**\r\n * Main agent execution function\r\n */\r\nexport async function executeAgent(\r\n definition: AgentDefinition,\r\n prompt: string,\r\n context: TaskContext,\r\n options: {\r\n method?: 'auto' | 'api' | 'script';\r\n } = {}\r\n): Promise<AgentExecutionResult> {\r\n const method = options.method || 'auto';\r\n\r\n // Auto-select execution method\r\n if (method === 'auto') {\r\n // Try API execution first, fallback to script if API key not available\r\n try {\r\n return await executeViaAPI(definition, prompt, context);\r\n } catch (error) {\r\n if (error instanceof Error && error.message.includes('API key not found')) {\r\n console.log('[agent-executor] API key not found, using script fallback');\r\n return executeViaScript(definition, prompt, context);\r\n }\r\n throw error;\r\n }\r\n }\r\n\r\n if (method === 'api') {\r\n return executeViaAPI(definition, prompt, context);\r\n }\r\n\r\n return executeViaScript(definition, prompt, context);\r\n}\r\n\r\n/**\r\n * Write agent output to file for debugging\r\n */\r\nexport async function saveAgentOutput(\r\n agentId: string,\r\n output: string,\r\n outputDir: string = '.claude/tmp/agent-output'\r\n): Promise<string> {\r\n await fs.mkdir(outputDir, { recursive: true });\r\n\r\n const timestamp = new Date().toISOString().replace(/[:.]/g, '-');\r\n const filename = `${agentId}-${timestamp}.txt`;\r\n const filepath = path.join(outputDir, filename);\r\n\r\n await fs.writeFile(filepath, output, 'utf-8');\r\n\r\n return filepath;\r\n}\r\n"],"names":["spawn","exec","promisify","getAgentId","buildCLIAgentSystemPrompt","loadContextFromEnv","loadMessages","storeMessage","getCurrentFork","formatMessagesForAPI","convertToolNames","fs","path","os","execSync","execAsync","getProjectRoot","process","env","PROJECT_ROOT","gitRoot","encoding","cwd","stdio","trim","projectRoot","redisHost","CFN_REDIS_HOST","redisPort","CFN_REDIS_PORT","redisPassword","CFN_REDIS_PASSWORD","REDIS_PASSWORD","parseContextToEnv","contextString","envVars","regex","match","key","quotedValue","unquotedValue","value","undefined","extractConfidence","output","patterns","pattern","score","parseFloat","executeCFNProtocol","taskId","agentId","iteration","enableIterations","maxIterations","console","log","authFlag","confidence","reportCmd","error","isCustomRoutingEnabled","CLAUDE_API_PROVIDER","configPath","join","config","JSON","parse","readFile","provider","getAPIProvider","customEnabled","executeViaAPI","definition","prompt","context","name","model","contextEnv","Object","keys","forkId","FORK_ID","systemPrompt","messages","forkMessages","length","content","slice","push","role","contextOptions","agentType","executeAgentAPI","tools","result","userMessage","timestamp","Date","toISOString","assistantMessage","success","exitCode","Error","message","String","executeViaScript","tmpDir","tmpdir","promptFile","now","writeFile","Promise","resolve","scriptPath","safeEnvVars","ANTHROPIC_API_KEY","AGENT_TYPE","AGENT_ID","AGENT_MODEL","AGENT_TOOLS","TASK_ID","ITERATION","MODE","mode","PROMPT_FILE","access","then","proc","on","code","err","catch","substring","executeAgent","options","method","includes","saveAgentOutput","outputDir","mkdir","recursive","replace","filename","filepath"],"mappings":"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"}