fraim-framework 2.0.38 → 2.0.41

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -255,6 +255,14 @@ FRAIM/
255
255
 
256
256
  ## 🚀 **Get Started in 60 Seconds**
257
257
 
258
+ ### **⚠️ Prerequisites**
259
+
260
+ **Shell Requirements:**
261
+ - **Windows**: Must use Git Bash (install from https://git-scm.com/download/win)
262
+ - **macOS/Linux**: Default terminal works fine
263
+
264
+ **Why Git Bash on Windows?** All FRAIM scripts use Unix-style paths and Bash commands. Git Bash ensures consistent behavior across platforms.
265
+
258
266
  ### **Install & Initialize**
259
267
  ```bash
260
268
  npm install -g fraim-framework
@@ -0,0 +1,162 @@
1
+ "use strict";
2
+ /**
3
+ * Simplified AI Manager
4
+ *
5
+ * Single AI manager integrated into fraim-mcp-server that reads validation rules
6
+ * from pre-defined JSON files and provides structured review instructions.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.AIManager = void 0;
10
+ const fs_1 = require("fs");
11
+ const path_1 = require("path");
12
+ class AIManager {
13
+ constructor(rulesPath) {
14
+ // Default to rules directory - server-side only, not sent to client
15
+ this.rulesPath = rulesPath || (0, path_1.join)(__dirname, '..', '..', 'registry', 'ai-manager-rules');
16
+ }
17
+ /**
18
+ * Generate review instructions for a workflow phase
19
+ */
20
+ generateReviewInstructions(context) {
21
+ console.log(`🤖 AI Manager: Generating review instructions for ${context.workflowType} phase`);
22
+ const rules = this.loadWorkflowRules(context.workflowType);
23
+ if (!rules) {
24
+ throw new Error(`No rules found for workflow type: ${context.workflowType}`);
25
+ }
26
+ return this.formatReviewInstructions(rules, context);
27
+ }
28
+ /**
29
+ * Evaluate agent's review report and provide decision
30
+ */
31
+ evaluateReport(report, context) {
32
+ console.log(`🤖 AI Manager: Evaluating review report for ${context.workflowType} phase`);
33
+ const iterationCount = report.iterationCount || 1;
34
+ const maxIterations = 3;
35
+ if (report.pass) {
36
+ return {
37
+ action: 'PROCEED',
38
+ message: 'Review passed. Ready to submit PR to human for review.',
39
+ nextSteps: [
40
+ 'Update issue status to "status:needs-review"',
41
+ 'Remove "status:wip" label',
42
+ 'Include complete review results in evidence document',
43
+ 'Submit PR for human review with evidence'
44
+ ],
45
+ iterationCount
46
+ };
47
+ }
48
+ else {
49
+ // Check if max iterations reached
50
+ if (iterationCount >= maxIterations) {
51
+ return {
52
+ action: 'ESCALATE',
53
+ message: `Maximum iterations (${maxIterations}) reached. Escalating to human review despite failing validation.`,
54
+ nextSteps: [
55
+ 'Update issue status to "status:needs-review"',
56
+ 'Add "ai-manager:max-iterations" label to indicate escalation reason',
57
+ 'Include all iteration attempts and failure reasons in evidence document',
58
+ 'Submit PR for human review with detailed iteration history',
59
+ 'Human reviewer should focus on the recurring validation failures'
60
+ ],
61
+ iterationCount,
62
+ maxIterationsReached: true
63
+ };
64
+ }
65
+ else {
66
+ return {
67
+ action: 'ITERATE',
68
+ message: `Review failed. Address the identified issues before proceeding. (Iteration ${iterationCount}/${maxIterations})`,
69
+ nextSteps: [
70
+ 'Fix all issues identified in the failure reasons',
71
+ 'Re-run validation steps to verify fixes',
72
+ `Request new review instructions with iterationCount: ${iterationCount + 1}`,
73
+ 'Do not submit PR until review passes or max iterations reached'
74
+ ],
75
+ iterationCount
76
+ };
77
+ }
78
+ }
79
+ }
80
+ /**
81
+ * Load workflow rules from JSON file (server-side only)
82
+ */
83
+ loadWorkflowRules(workflowType) {
84
+ const rulesFile = (0, path_1.join)(this.rulesPath, `${workflowType}.json`);
85
+ if (!(0, fs_1.existsSync)(rulesFile)) {
86
+ console.warn(`⚠️ No rules file found for workflow: ${workflowType} at ${rulesFile}`);
87
+ return null;
88
+ }
89
+ try {
90
+ const content = (0, fs_1.readFileSync)(rulesFile, 'utf8');
91
+ return JSON.parse(content);
92
+ }
93
+ catch (error) {
94
+ console.error(`❌ Error loading rules for ${workflowType}:`, error);
95
+ return null;
96
+ }
97
+ }
98
+ /**
99
+ * Format review instructions with proper template structure
100
+ */
101
+ formatReviewInstructions(rules, context) {
102
+ const instructions = `# AI Manager Review Instructions
103
+
104
+ ## Workflow: ${rules.workflowType.toUpperCase()}
105
+ **Issue:** #${context.issueNumber}
106
+ **Phase:** ${context.phase}
107
+
108
+ ## Description
109
+ ${rules.description}
110
+
111
+ ## Iteration Tracking
112
+ **IMPORTANT**: You must track your iteration count for this phase. This is your attempt number for this specific workflow phase (spec, implement, test, etc.).
113
+
114
+ - **First attempt**: Use iterationCount: 1
115
+ - **After first failure**: Use iterationCount: 2
116
+ - **After second failure**: Use iterationCount: 3
117
+ - **Maximum iterations**: 3 (after 3rd failure, work will be escalated to human review)
118
+
119
+ ## Validation Steps
120
+ Complete each step below and evaluate whether you meet the pass criteria:
121
+
122
+ ${rules.validationRules.map(rule => `
123
+ ### Step ${rule.step}: ${rule.description}
124
+ ${rule.command ? `**Command:** \`${rule.command.replace('{issue_number}', context.issueNumber)}\`` : ''}
125
+ **Pass Criteria:** ${rule.passCriteria}
126
+ **Weight:** ${rule.weight.toUpperCase()}${rule.weight === 'blocking' ? ' (Must pass to proceed)' : ' (Should pass for quality)'}
127
+ **Category:** ${rule.category}
128
+ `).join('')}
129
+
130
+ ## Grading Criteria
131
+
132
+ ### Pass Requirements
133
+ ${rules.gradingCriteria.passRequirements.map(req => `- ${req}`).join('\n')}
134
+
135
+ ### Fail Requirements
136
+ ${rules.gradingCriteria.failRequirements.map(req => `- ${req}`).join('\n')}
137
+
138
+ ## Reporting Format
139
+ ${rules.reportingFormat.instructions}
140
+
141
+ **Required Response Format:**
142
+ \`\`\`json
143
+ {
144
+ "pass": true/false,
145
+ "reasons": ["reason1", "reason2"], // Only required if pass=false
146
+ "iterationCount": 1 // REQUIRED: Your current iteration number for this phase
147
+ }
148
+ \`\`\`
149
+
150
+ ## Iteration Limits
151
+ - **Maximum 3 iterations** per workflow phase
152
+ - After 3 failed attempts, work will be **automatically escalated** to human review
153
+ - Track your attempts carefully - include iterationCount in every report
154
+ - Each workflow phase (spec, implement, test) has its own iteration counter
155
+
156
+ ## Next Steps
157
+ After completing your review, report back with the JSON response above including your iteration count. The AI Manager will evaluate your report and provide next steps based on your progress and iteration count.
158
+ `;
159
+ return instructions;
160
+ }
161
+ }
162
+ exports.AIManager = AIManager;
@@ -286,7 +286,7 @@ const autoConfigureMCP = async (fraimKey, githubToken, selectedIDEs) => {
286
286
  const detectedIDEs = (0, ide_detector_1.detectInstalledIDEs)();
287
287
  if (detectedIDEs.length === 0) {
288
288
  console.log(chalk_1.default.yellow('⚠️ No supported IDEs detected.'));
289
- console.log(chalk_1.default.gray('Supported IDEs: Claude Desktop, Antigravity, Kiro, Cursor, VSCode, Codex, Windsurf'));
289
+ console.log(chalk_1.default.gray('Supported IDEs: Claude, Antigravity, Kiro, Cursor, VSCode, Codex, Windsurf'));
290
290
  console.log(chalk_1.default.blue('\n💡 You can install an IDE and run setup again later.'));
291
291
  console.log(chalk_1.default.gray(' Or continue with manual MCP configuration.'));
292
292
  const continueAnyway = await (0, prompts_1.default)({
@@ -19,6 +19,7 @@ const checkMultiplePaths = (paths) => {
19
19
  };
20
20
  const detectClaude = () => {
21
21
  const paths = [
22
+ '~/.claude.json',
22
23
  '~/.claude',
23
24
  '~/Library/Application Support/Claude',
24
25
  '~/AppData/Roaming/Claude'
@@ -54,16 +55,17 @@ const detectWindsurf = () => {
54
55
  };
55
56
  exports.IDE_CONFIGS = [
56
57
  {
57
- name: 'Claude Desktop',
58
- configPath: '~/.claude/settings.json',
58
+ name: 'Claude',
59
+ configPath: '~/.claude.json',
59
60
  configFormat: 'json',
60
- configType: 'standard',
61
+ configType: 'claude',
61
62
  detectMethod: detectClaude,
62
63
  alternativePaths: [
64
+ '~/.claude/settings.json',
63
65
  '~/Library/Application Support/Claude/settings.json',
64
66
  '~/AppData/Roaming/Claude/settings.json'
65
67
  ],
66
- description: 'Anthropic Claude Desktop application'
68
+ description: 'Anthropic Claude application'
67
69
  },
68
70
  {
69
71
  name: 'Antigravity',
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.generateMCPConfig = exports.generateWindsurfMCPServers = exports.generateCodexMCPServers = exports.generateKiroMCPServers = exports.generateStandardMCPServers = void 0;
3
+ exports.generateMCPConfig = exports.generateWindsurfMCPServers = exports.generateCodexMCPServers = exports.generateKiroMCPServers = exports.generateClaudeMCPServers = exports.generateStandardMCPServers = void 0;
4
4
  const generateStandardMCPServers = (fraimKey, githubToken) => ({
5
5
  mcpServers: {
6
6
  git: {
@@ -26,6 +26,33 @@ const generateStandardMCPServers = (fraimKey, githubToken) => ({
26
26
  }
27
27
  });
28
28
  exports.generateStandardMCPServers = generateStandardMCPServers;
29
+ const generateClaudeMCPServers = (fraimKey, githubToken) => ({
30
+ mcpServers: {
31
+ git: {
32
+ command: "npx",
33
+ args: ["-y", "@cyanheads/git-mcp-server"]
34
+ },
35
+ github: {
36
+ type: "http",
37
+ url: "https://api.githubcopilot.com/mcp/",
38
+ headers: {
39
+ Authorization: `Bearer ${githubToken}`
40
+ }
41
+ },
42
+ playwright: {
43
+ command: "npx",
44
+ args: ["-y", "@playwright/mcp"]
45
+ },
46
+ fraim: {
47
+ type: "http",
48
+ url: "https://fraim.wellnessatwork.me",
49
+ headers: {
50
+ "x-api-key": fraimKey
51
+ }
52
+ }
53
+ }
54
+ });
55
+ exports.generateClaudeMCPServers = generateClaudeMCPServers;
29
56
  const generateKiroMCPServers = (fraimKey, githubToken) => ({
30
57
  mcpServers: {
31
58
  git: {
@@ -102,6 +129,8 @@ const generateMCPConfig = (configType, fraimKey, githubToken) => {
102
129
  switch (configType) {
103
130
  case 'standard':
104
131
  return (0, exports.generateStandardMCPServers)(fraimKey, githubToken);
132
+ case 'claude':
133
+ return (0, exports.generateClaudeMCPServers)(fraimKey, githubToken);
105
134
  case 'kiro':
106
135
  return (0, exports.generateKiroMCPServers)(fraimKey, githubToken);
107
136
  case 'codex':
@@ -45,6 +45,7 @@ const path_1 = require("path");
45
45
  const git_utils_1 = require("./utils/git-utils");
46
46
  const config_loader_1 = require("./fraim/config-loader");
47
47
  const db_service_1 = require("./fraim/db-service");
48
+ const ai_manager_1 = require("./ai-manager/ai-manager");
48
49
  const issues_1 = require("./fraim/issues");
49
50
  const crypto_1 = require("crypto");
50
51
  const dotenv = __importStar(require("dotenv"));
@@ -169,6 +170,7 @@ class FraimMCPServer {
169
170
  // Initialize database service
170
171
  this.dbService = new db_service_1.FraimDbService();
171
172
  this.sessionManager = new SessionManager(this.dbService);
173
+ this.aiManager = new ai_manager_1.AIManager();
172
174
  // Load FRAIM configuration
173
175
  this.config = (0, config_loader_1.loadFraimConfig)();
174
176
  // Find registry directory (check dist first for production, then source)
@@ -979,6 +981,98 @@ Supports dry-run mode to preview the operation.`,
979
981
  },
980
982
  required: ['title', 'body']
981
983
  }
984
+ },
985
+ {
986
+ name: 'ai_manager_request_review',
987
+ description: `Request self-review instructions from AI Manager after completing workflow phase.
988
+
989
+ The AI Manager provides detailed review instructions including:
990
+ - Step-by-step validation criteria
991
+ - Pass/fail criteria for each step
992
+ - Commands to run for verification
993
+ - Grading guidelines and reporting format
994
+
995
+ Use this when you believe your work is complete and ready for review.
996
+ Currently supports: spec phase (more phases coming soon).`,
997
+ inputSchema: {
998
+ type: 'object',
999
+ properties: {
1000
+ workflowType: {
1001
+ type: 'string',
1002
+ description: 'Type of workflow phase completed',
1003
+ enum: ['spec', 'design', 'implement', 'test']
1004
+ },
1005
+ issueNumber: {
1006
+ type: 'string',
1007
+ description: 'Issue number being worked on'
1008
+ },
1009
+ phase: {
1010
+ type: 'string',
1011
+ description: 'Specific phase name (e.g., "specification", "implementation")'
1012
+ }
1013
+ },
1014
+ required: ['workflowType', 'issueNumber', 'phase']
1015
+ }
1016
+ },
1017
+ {
1018
+ name: 'ai_manager_report_grade',
1019
+ description: `Report your self-assessment to AI Manager after completing self-review.
1020
+
1021
+ Provide results from review in JSON format:
1022
+ - pass: true/false based on review assessment
1023
+ - reasons: array of failure reasons (only if pass=false)
1024
+ - iterationCount: REQUIRED - your current iteration number for this phase
1025
+
1026
+ AI Manager will evaluate your report and provide next steps:
1027
+ - PROCEED: Ready to submit PR for human review
1028
+ - ITERATE: Fix issues and retry (max 3 iterations)
1029
+ - ESCALATE: Max iterations reached, escalate to human review
1030
+
1031
+ IMPORTANT: Track your iteration count per workflow phase. Each phase (spec, implement, test) has its own counter.
1032
+ Maximum 3 iterations per phase before automatic escalation to human review.`,
1033
+ inputSchema: {
1034
+ type: 'object',
1035
+ properties: {
1036
+ workflowType: {
1037
+ type: 'string',
1038
+ description: 'Type of workflow phase',
1039
+ enum: ['spec', 'design', 'implement', 'test']
1040
+ },
1041
+ issueNumber: {
1042
+ type: 'string',
1043
+ description: 'Issue number being worked on'
1044
+ },
1045
+ phase: {
1046
+ type: 'string',
1047
+ description: 'Specific phase name'
1048
+ },
1049
+ report: {
1050
+ type: 'object',
1051
+ description: 'Your self-assessment report in JSON format',
1052
+ properties: {
1053
+ pass: {
1054
+ type: 'boolean',
1055
+ description: 'Whether your work passes all validation criteria'
1056
+ },
1057
+ reasons: {
1058
+ type: 'array',
1059
+ description: 'Array of specific reasons for failure (only required if pass=false)',
1060
+ items: {
1061
+ type: 'string'
1062
+ }
1063
+ },
1064
+ iterationCount: {
1065
+ type: 'number',
1066
+ description: 'REQUIRED: Your current iteration number for this workflow phase (1, 2, or 3)',
1067
+ minimum: 1,
1068
+ maximum: 3
1069
+ }
1070
+ },
1071
+ required: ['pass', 'iterationCount']
1072
+ }
1073
+ },
1074
+ required: ['workflowType', 'issueNumber', 'phase', 'report']
1075
+ }
982
1076
  }
983
1077
  ]
984
1078
  };
@@ -1016,6 +1110,10 @@ Supports dry-run mode to preview the operation.`,
1016
1110
  };
1017
1111
  case 'fraim_connect':
1018
1112
  return await this.handleFraimConnect(toolArgs, context.apiKey, context.userId);
1113
+ case 'ai_manager_request_review':
1114
+ return await this.handleAIManagerRequestReview(toolArgs);
1115
+ case 'ai_manager_report_grade':
1116
+ return await this.handleAIManagerReportGrade(toolArgs);
1019
1117
  default:
1020
1118
  throw new Error(`Unknown tool: ${toolName} `);
1021
1119
  }
@@ -1450,6 +1548,106 @@ If \`.fraim/config.json\` doesn't exist:
1450
1548
  sessionId: sessionId
1451
1549
  };
1452
1550
  }
1551
+ async handleAIManagerRequestReview(args) {
1552
+ try {
1553
+ console.log(`🤖 AI Manager: Generating review instructions for ${args.workflowType} phase`);
1554
+ const instructions = this.aiManager.generateReviewInstructions({
1555
+ workflowType: args.workflowType,
1556
+ issueNumber: args.issueNumber,
1557
+ phase: args.phase
1558
+ });
1559
+ return {
1560
+ content: [{
1561
+ type: 'text',
1562
+ text: instructions
1563
+ }]
1564
+ };
1565
+ }
1566
+ catch (error) {
1567
+ console.error('❌ AI Manager request review failed:', error);
1568
+ return {
1569
+ content: [{
1570
+ type: 'text',
1571
+ text: `# ❌ AI Manager Request Failed\n\n**Error**: ${error instanceof Error ? error.message : 'Unknown error'}\n\nPlease check your request parameters and try again.`
1572
+ }],
1573
+ error: error instanceof Error ? error.message : 'Unknown error'
1574
+ };
1575
+ }
1576
+ }
1577
+ async handleAIManagerReportGrade(args) {
1578
+ try {
1579
+ console.log(`🤖 AI Manager: Evaluating review report for ${args.workflowType} phase`);
1580
+ const decision = this.aiManager.evaluateReport(args.report, {
1581
+ workflowType: args.workflowType,
1582
+ issueNumber: args.issueNumber,
1583
+ phase: args.phase
1584
+ });
1585
+ // Format response for agent
1586
+ let response = `# 🤖 AI Manager Evaluation Result\n\n`;
1587
+ const actionEmoji = decision.action === 'PROCEED' ? '✅' :
1588
+ decision.action === 'ESCALATE' ? '⚠️' : '🔄';
1589
+ response += `## Decision: ${actionEmoji} ${decision.action}\n\n`;
1590
+ response += `**Message**: ${decision.message}\n\n`;
1591
+ if (decision.iterationCount) {
1592
+ response += `**Iteration Count**: ${decision.iterationCount}/3\n\n`;
1593
+ }
1594
+ response += `## Next Steps\n\n`;
1595
+ decision.nextSteps.forEach((step, index) => {
1596
+ response += `${index + 1}. ${step}\n`;
1597
+ });
1598
+ response += `\n`;
1599
+ if (decision.action === 'PROCEED') {
1600
+ response += `## 🎉 Ready for Human Review!\n\n`;
1601
+ response += `Your work has passed AI Manager validation. You should now:\n\n`;
1602
+ response += `1. **Submit PR** with complete evidence document\n`;
1603
+ response += `2. **Update issue labels** to status:needs-review\n`;
1604
+ response += `3. **Include this AI Manager validation** in your evidence\n\n`;
1605
+ }
1606
+ else if (decision.action === 'ESCALATE') {
1607
+ response += `## ⚠️ Escalated to Human Review\n\n`;
1608
+ response += `Maximum iterations reached. Your work will be reviewed by a human despite validation failures:\n\n`;
1609
+ response += `1. **Submit PR** with detailed iteration history\n`;
1610
+ response += `2. **Add escalation label** (ai-manager:max-iterations)\n`;
1611
+ response += `3. **Document all attempts** and failure reasons in evidence\n`;
1612
+ response += `4. **Human reviewer** will focus on recurring validation issues\n\n`;
1613
+ }
1614
+ else {
1615
+ response += `## 🔧 Work Required\n\n`;
1616
+ response += `Your work needs improvement. You should:\n\n`;
1617
+ response += `1. **Address all failure reasons** listed below\n`;
1618
+ response += `2. **Re-run validation steps** to verify fixes\n`;
1619
+ response += `3. **Request new review** using ai_manager_request_review\n`;
1620
+ response += `4. **Include iterationCount: ${(decision.iterationCount || 1) + 1}** in next report\n`;
1621
+ response += `5. **Do NOT submit PR** until review passes or escalates\n\n`;
1622
+ }
1623
+ response += `## Your Report Summary\n\n`;
1624
+ response += `**Pass**: ${args.report.pass}\n`;
1625
+ response += `**Iteration**: ${args.report.iterationCount || 1}/3\n`;
1626
+ if (args.report.reasons && args.report.reasons.length > 0) {
1627
+ response += `**Failure Reasons**:\n`;
1628
+ args.report.reasons.forEach((reason) => {
1629
+ response += `- ${reason}\n`;
1630
+ });
1631
+ }
1632
+ return {
1633
+ content: [{
1634
+ type: 'text',
1635
+ text: response
1636
+ }],
1637
+ decision: decision
1638
+ };
1639
+ }
1640
+ catch (error) {
1641
+ console.error('❌ AI Manager report evaluation failed:', error);
1642
+ return {
1643
+ content: [{
1644
+ type: 'text',
1645
+ text: `# ❌ AI Manager Evaluation Failed\n\n**Error**: ${error instanceof Error ? error.message : 'Unknown error'}\n\nPlease check your report format and try again.`
1646
+ }],
1647
+ error: error instanceof Error ? error.message : 'Unknown error'
1648
+ };
1649
+ }
1650
+ }
1453
1651
  async start(port = 3002) {
1454
1652
  try {
1455
1653
  // Connect to database before starting server
@@ -0,0 +1,113 @@
1
+ "use strict";
2
+ /**
3
+ * Tests for AI Manager - Simplified Review System
4
+ */
5
+ var __importDefault = (this && this.__importDefault) || function (mod) {
6
+ return (mod && mod.__esModule) ? mod : { "default": mod };
7
+ };
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ const node_test_1 = require("node:test");
10
+ const node_assert_1 = __importDefault(require("node:assert"));
11
+ const ai_manager_1 = require("../src/ai-manager/ai-manager");
12
+ (0, node_test_1.describe)('AI Manager', () => {
13
+ let aiManager;
14
+ (0, node_test_1.beforeEach)(() => {
15
+ aiManager = new ai_manager_1.AIManager();
16
+ });
17
+ (0, node_test_1.describe)('generateReviewInstructions', () => {
18
+ (0, node_test_1.test)('should generate spec workflow instructions', () => {
19
+ const context = {
20
+ workflowType: 'spec',
21
+ issueNumber: '123',
22
+ phase: 'specification'
23
+ };
24
+ const instructions = aiManager.generateReviewInstructions(context);
25
+ (0, node_assert_1.default)(typeof instructions === 'string');
26
+ (0, node_assert_1.default)(instructions.includes('AI Manager Review Instructions'));
27
+ (0, node_assert_1.default)(instructions.includes('spec'));
28
+ (0, node_assert_1.default)(instructions.includes('123'));
29
+ (0, node_assert_1.default)(instructions.includes('iterationCount'));
30
+ (0, node_assert_1.default)(instructions.includes('Maximum 3 iterations'));
31
+ });
32
+ (0, node_test_1.test)('should throw error for unknown workflow type', () => {
33
+ const context = {
34
+ workflowType: 'unknown',
35
+ issueNumber: '123',
36
+ phase: 'test'
37
+ };
38
+ node_assert_1.default.throws(() => {
39
+ aiManager.generateReviewInstructions(context);
40
+ }, /No rules found for workflow type: unknown/);
41
+ });
42
+ });
43
+ (0, node_test_1.describe)('evaluateReport', () => {
44
+ (0, node_test_1.test)('should return PROCEED for passing report', () => {
45
+ const report = {
46
+ pass: true,
47
+ iterationCount: 1
48
+ };
49
+ const context = {
50
+ workflowType: 'spec',
51
+ issueNumber: '123',
52
+ phase: 'specification'
53
+ };
54
+ const decision = aiManager.evaluateReport(report, context);
55
+ node_assert_1.default.strictEqual(decision.action, 'PROCEED');
56
+ (0, node_assert_1.default)(decision.message.includes('Ready to submit PR'));
57
+ (0, node_assert_1.default)(decision.nextSteps.length > 0);
58
+ node_assert_1.default.strictEqual(decision.iterationCount, 1);
59
+ });
60
+ (0, node_test_1.test)('should return ITERATE for failing report within iteration limit', () => {
61
+ const report = {
62
+ pass: false,
63
+ reasons: ['Missing spec document', 'Template not followed'],
64
+ iterationCount: 2
65
+ };
66
+ const context = {
67
+ workflowType: 'spec',
68
+ issueNumber: '123',
69
+ phase: 'specification'
70
+ };
71
+ const decision = aiManager.evaluateReport(report, context);
72
+ node_assert_1.default.strictEqual(decision.action, 'ITERATE');
73
+ (0, node_assert_1.default)(decision.message.includes('Address the identified issues'));
74
+ (0, node_assert_1.default)(decision.message.includes('Iteration 2/3'));
75
+ (0, node_assert_1.default)(decision.nextSteps.length > 0);
76
+ node_assert_1.default.strictEqual(decision.iterationCount, 2);
77
+ });
78
+ (0, node_test_1.test)('should return ESCALATE when max iterations reached', () => {
79
+ const report = {
80
+ pass: false,
81
+ reasons: ['Still missing spec document', 'Template still not followed'],
82
+ iterationCount: 3
83
+ };
84
+ const context = {
85
+ workflowType: 'spec',
86
+ issueNumber: '123',
87
+ phase: 'specification'
88
+ };
89
+ const decision = aiManager.evaluateReport(report, context);
90
+ node_assert_1.default.strictEqual(decision.action, 'ESCALATE');
91
+ (0, node_assert_1.default)(decision.message.includes('Maximum iterations'));
92
+ (0, node_assert_1.default)(decision.message.includes('Escalating to human review'));
93
+ (0, node_assert_1.default)(decision.nextSteps.length > 0);
94
+ node_assert_1.default.strictEqual(decision.iterationCount, 3);
95
+ node_assert_1.default.strictEqual(decision.maxIterationsReached, true);
96
+ });
97
+ (0, node_test_1.test)('should default to iteration 1 if not provided', () => {
98
+ const report = {
99
+ pass: false,
100
+ reasons: ['Missing spec document']
101
+ // iterationCount not provided
102
+ };
103
+ const context = {
104
+ workflowType: 'spec',
105
+ issueNumber: '123',
106
+ phase: 'specification'
107
+ };
108
+ const decision = aiManager.evaluateReport(report, context);
109
+ node_assert_1.default.strictEqual(decision.action, 'ITERATE');
110
+ node_assert_1.default.strictEqual(decision.iterationCount, 1);
111
+ });
112
+ });
113
+ });
@@ -95,7 +95,7 @@ const token_validator_1 = require("../src/cli/setup/token-validator");
95
95
  (0, node_test_1.test)('Path expansion works correctly across platforms', () => {
96
96
  const testPaths = [
97
97
  '~/.fraim/config.json',
98
- '~/.claude/settings.json',
98
+ '~/.claude.json',
99
99
  '~/.kiro/settings/mcp.json'
100
100
  ];
101
101
  testPaths.forEach(testPath => {
@@ -19,14 +19,14 @@ const os_1 = __importDefault(require("os"));
19
19
  node_assert_1.default.strictEqual(result, absolutePath);
20
20
  });
21
21
  (0, node_test_1.test)('IDE_CONFIGS should contain all expected IDEs', () => {
22
- const expectedIDEs = ['Claude Desktop', 'Antigravity', 'Kiro', 'Cursor', 'VSCode', 'Codex', 'Windsurf'];
22
+ const expectedIDEs = ['Claude', 'Antigravity', 'Kiro', 'Cursor', 'VSCode', 'Codex', 'Windsurf'];
23
23
  const actualIDEs = ide_detector_1.IDE_CONFIGS.map(ide => ide.name);
24
24
  expectedIDEs.forEach(expectedIDE => {
25
25
  (0, node_assert_1.default)(actualIDEs.includes(expectedIDE), `Missing IDE: ${expectedIDE}`);
26
26
  });
27
27
  });
28
28
  (0, node_test_1.test)('IDE_CONFIGS should have valid config types', () => {
29
- const validConfigTypes = ['standard', 'kiro', 'codex', 'windsurf'];
29
+ const validConfigTypes = ['standard', 'kiro', 'codex', 'windsurf', 'claude'];
30
30
  ide_detector_1.IDE_CONFIGS.forEach(ide => {
31
31
  (0, node_assert_1.default)(validConfigTypes.includes(ide.configType), `Invalid config type for ${ide.name}: ${ide.configType}`);
32
32
  });
@@ -30,12 +30,12 @@ const mcp_config_generator_1 = require("../src/cli/setup/mcp-config-generator");
30
30
  const claude = (0, ide_detector_1.findIDEByName)('claude');
31
31
  const cursor = (0, ide_detector_1.findIDEByName)('cursor');
32
32
  const vscode = (0, ide_detector_1.findIDEByName)('vscode');
33
- (0, node_assert_1.default)(claude?.name === 'Claude Desktop', 'Should find Claude Desktop');
33
+ (0, node_assert_1.default)(claude?.name === 'Claude', 'Should find Claude');
34
34
  (0, node_assert_1.default)(cursor?.name === 'Cursor', 'Should find Cursor');
35
35
  (0, node_assert_1.default)(vscode?.name === 'VSCode', 'Should find VSCode');
36
36
  // Test partial matching
37
37
  const claudePartial = (0, ide_detector_1.findIDEByName)('clau');
38
- (0, node_assert_1.default)(claudePartial?.name === 'Claude Desktop', 'Should find Claude with partial name');
38
+ (0, node_assert_1.default)(claudePartial?.name === 'Claude', 'Should find Claude with partial name');
39
39
  console.log('✅ IDE name matching works correctly');
40
40
  });
41
41
  (0, node_test_1.it)('should expand paths correctly across platforms', () => {