@limo-labs/limo-cli 0.1.0-alpha.0

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 (42) hide show
  1. package/README.md +238 -0
  2. package/dist/agents/analyst.d.ts +24 -0
  3. package/dist/agents/analyst.js +128 -0
  4. package/dist/agents/editor.d.ts +26 -0
  5. package/dist/agents/editor.js +157 -0
  6. package/dist/agents/planner-validator.d.ts +7 -0
  7. package/dist/agents/planner-validator.js +125 -0
  8. package/dist/agents/planner.d.ts +56 -0
  9. package/dist/agents/planner.js +186 -0
  10. package/dist/agents/writer.d.ts +25 -0
  11. package/dist/agents/writer.js +164 -0
  12. package/dist/commands/analyze.d.ts +14 -0
  13. package/dist/commands/analyze.js +562 -0
  14. package/dist/index.d.ts +2 -0
  15. package/dist/index.js +41 -0
  16. package/dist/report/diagrams.d.ts +27 -0
  17. package/dist/report/diagrams.js +74 -0
  18. package/dist/report/graphCompiler.d.ts +37 -0
  19. package/dist/report/graphCompiler.js +277 -0
  20. package/dist/report/markdownGenerator.d.ts +71 -0
  21. package/dist/report/markdownGenerator.js +148 -0
  22. package/dist/tools/additional.d.ts +116 -0
  23. package/dist/tools/additional.js +349 -0
  24. package/dist/tools/extended.d.ts +101 -0
  25. package/dist/tools/extended.js +586 -0
  26. package/dist/tools/index.d.ts +86 -0
  27. package/dist/tools/index.js +362 -0
  28. package/dist/types/agents.types.d.ts +139 -0
  29. package/dist/types/agents.types.js +6 -0
  30. package/dist/types/graphSemantics.d.ts +99 -0
  31. package/dist/types/graphSemantics.js +104 -0
  32. package/dist/utils/debug.d.ts +28 -0
  33. package/dist/utils/debug.js +125 -0
  34. package/dist/utils/limoConfigParser.d.ts +21 -0
  35. package/dist/utils/limoConfigParser.js +274 -0
  36. package/dist/utils/reviewMonitor.d.ts +20 -0
  37. package/dist/utils/reviewMonitor.js +121 -0
  38. package/package.json +62 -0
  39. package/prompts/analyst.md +343 -0
  40. package/prompts/editor.md +196 -0
  41. package/prompts/planner.md +388 -0
  42. package/prompts/writer.md +218 -0
@@ -0,0 +1,125 @@
1
+ /**
2
+ * Planner Validator - Validates that planner created a comprehensive analysis plan
3
+ */
4
+ export class PlannerValidator {
5
+ async validate(ctx, loopState) {
6
+ const inputs = ctx.inputs;
7
+ // 1. Check if planning_create was called
8
+ const allToolCalls = [
9
+ ...loopState.toolCallsThisRound,
10
+ // Also check previous rounds from messages
11
+ ...loopState.messages
12
+ .filter((msg) => msg.role === 'assistant' && msg.toolCalls)
13
+ .flatMap((msg) => msg.toolCalls || [])
14
+ ];
15
+ const planningCall = allToolCalls.find(tc => tc.name === 'planning_create');
16
+ if (!planningCall) {
17
+ return {
18
+ valid: false,
19
+ feedback: `⚠️ CRITICAL: You must call the planning_create tool to create the analysis plan.
20
+
21
+ **Required Steps**:
22
+ 1. Call file_list with pattern "**/*" to scan project files
23
+ 2. Store project insights using memory_store
24
+ 3. Call planning_create with comprehensive task list
25
+
26
+ Please follow the workflow and call planning_create to complete this task.`
27
+ };
28
+ }
29
+ const planArgs = planningCall.arguments;
30
+ // 2. Check plan has tasks
31
+ if (!planArgs.tasks || planArgs.tasks.length === 0) {
32
+ return {
33
+ valid: false,
34
+ feedback: `⚠️ QUALITY ISSUE: The planning_create tool was called but with no tasks.
35
+
36
+ Please create a comprehensive analysis plan with multiple tasks covering all required modules.`
37
+ };
38
+ }
39
+ // 3. Check minimum task count based on project complexity
40
+ const minTasksByComplexity = {
41
+ small: 5,
42
+ medium: 10,
43
+ large: 15
44
+ };
45
+ const complexity = planArgs.project_complexity || 'medium';
46
+ const requiredMin = minTasksByComplexity[complexity] || 10;
47
+ if (planArgs.tasks.length < requiredMin) {
48
+ return {
49
+ valid: false,
50
+ feedback: `⚠️ QUALITY ISSUE: Your plan has only ${planArgs.tasks.length} tasks, but ${complexity} projects require at least ${requiredMin} tasks.
51
+
52
+ **Please improve your plan**:
53
+ - Scan the project structure with file_list
54
+ - Identify all major components/packages
55
+ - Create specific tasks for each area (e.g., "Analyze Spring MVC controllers", "Review database schema")
56
+ - Each module should have 2-3 detailed tasks
57
+
58
+ Call planning_create again with a more comprehensive task list.`
59
+ };
60
+ }
61
+ // 4. Check for estimated_files (must have scanned project)
62
+ if (!planArgs.estimated_files || planArgs.estimated_files === 0) {
63
+ return {
64
+ valid: false,
65
+ feedback: `⚠️ CRITICAL: You must call file_list to scan the project and get the actual file count.
66
+
67
+ **Required**:
68
+ 1. Call file_list with pattern "**/*"
69
+ 2. Use the ACTUAL file count in planning_create
70
+ 3. Don't guess the file count!
71
+
72
+ Please scan the project first, then call planning_create with accurate data.`
73
+ };
74
+ }
75
+ // 5. Check for trivial tasks
76
+ const trivialPatterns = ['verify', 'check setup', 'initialize', 'validate', 'confirm'];
77
+ const trivialTasks = planArgs.tasks.filter((task) => trivialPatterns.some(pattern => task.title.toLowerCase().includes(pattern)));
78
+ if (trivialTasks.length > planArgs.tasks.length * 0.3) {
79
+ return {
80
+ valid: false,
81
+ feedback: `⚠️ QUALITY ISSUE: ${trivialTasks.length}/${planArgs.tasks.length} tasks appear to be trivial setup/verification tasks.
82
+
83
+ **Please create meaningful analysis tasks**:
84
+ - Focus on actual code analysis, not setup
85
+ - Each task should analyze specific files/packages
86
+ - Tasks should produce substantial documentation (600-1200 words)
87
+
88
+ Examples of good tasks:
89
+ - "Analyze Spring MVC controller architecture in owner/ package"
90
+ - "Review JPA entity relationships and database schema"
91
+ - "Document REST API endpoints and request/response patterns"
92
+
93
+ Please revise your plan with more substantive analysis tasks.`
94
+ };
95
+ }
96
+ // 6. Check task descriptions are specific
97
+ const vagueDescriptions = planArgs.tasks.filter((task) => {
98
+ const desc = (task.description || '').toLowerCase();
99
+ return desc.length < 50 ||
100
+ (!desc.includes('file') && !desc.includes('package') && !desc.includes('class'));
101
+ });
102
+ if (vagueDescriptions.length > planArgs.tasks.length * 0.4) {
103
+ return {
104
+ valid: false,
105
+ feedback: `⚠️ QUALITY ISSUE: ${vagueDescriptions.length}/${planArgs.tasks.length} tasks have vague descriptions.
106
+
107
+ **Task descriptions should be specific**:
108
+ - Mention which files/packages to analyze
109
+ - Describe what patterns to look for
110
+ - Explain what the task should document
111
+
112
+ Example:
113
+ ❌ Bad: "Analyze architecture"
114
+ ✅ Good: "Analyze Spring MVC architecture in src/main/java/owner/ package, focusing on controller-service-repository pattern"
115
+
116
+ Please improve task descriptions to be more specific and actionable.`
117
+ };
118
+ }
119
+ // All validations passed!
120
+ return {
121
+ valid: true,
122
+ message: `✅ Analysis plan successfully validated with ${planArgs.tasks.length} comprehensive tasks for ${complexity} project.`
123
+ };
124
+ }
125
+ }
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Planner Agent - Creates comprehensive analysis plans
3
+ * Using declarative TSX syntax
4
+ */
5
+ import { z } from 'zod';
6
+ import { type AgentNode } from '@limo-labs/deity';
7
+ declare const PlannerInputSchema: z.ZodObject<{
8
+ workspaceRoot: z.ZodString;
9
+ modules: z.ZodOptional<z.ZodArray<z.ZodString>>;
10
+ limoConfig: z.ZodOptional<z.ZodAny>;
11
+ }, z.core.$strip>;
12
+ export type PlannerInput = z.infer<typeof PlannerInputSchema>;
13
+ declare const PlannerOutputSchema: z.ZodObject<{
14
+ project_complexity: z.ZodEnum<{
15
+ small: "small";
16
+ medium: "medium";
17
+ large: "large";
18
+ }>;
19
+ estimated_loc: z.ZodNumber;
20
+ estimated_files: z.ZodNumber;
21
+ tasks: z.ZodArray<z.ZodObject<{
22
+ task_id: z.ZodString;
23
+ module: z.ZodString;
24
+ title: z.ZodString;
25
+ description: z.ZodString;
26
+ required_outputs: z.ZodObject<{
27
+ report_sections: z.ZodNumber;
28
+ code_examples: z.ZodNumber;
29
+ diagrams: z.ZodNumber;
30
+ min_word_count: z.ZodNumber;
31
+ }, z.core.$strip>;
32
+ memory_keys_to_generate: z.ZodOptional<z.ZodArray<z.ZodString>>;
33
+ dependencies: z.ZodArray<z.ZodString>;
34
+ status: z.ZodEnum<{
35
+ pending: "pending";
36
+ in_progress: "in_progress";
37
+ completed: "completed";
38
+ failed: "failed";
39
+ }>;
40
+ }, z.core.$strip>>;
41
+ total_tasks: z.ZodNumber;
42
+ estimated_duration_minutes: z.ZodOptional<z.ZodNumber>;
43
+ created_at: z.ZodString;
44
+ summary: z.ZodObject<{
45
+ tasks_by_module: z.ZodRecord<z.ZodString, z.ZodNumber>;
46
+ total_sections_expected: z.ZodNumber;
47
+ total_diagrams_expected: z.ZodNumber;
48
+ total_words_expected: z.ZodNumber;
49
+ }, z.core.$strip>;
50
+ }, z.core.$strip>;
51
+ type PlannerOutput = z.infer<typeof PlannerOutputSchema>;
52
+ /**
53
+ * Create Planner Agent using declarative TSX syntax
54
+ */
55
+ export declare function createPlannerAgent(promptsDir: string): AgentNode<PlannerInput, PlannerOutput>;
56
+ export {};
@@ -0,0 +1,186 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "@limo-labs/deity/jsx-runtime";
2
+ /**
3
+ * Planner Agent - Creates comprehensive analysis plans
4
+ * Using declarative TSX syntax
5
+ */
6
+ import { z } from 'zod';
7
+ import { Agent, Prompt, System, User, Result } from '@limo-labs/deity';
8
+ import { extractLastToolResult } from '@limo-labs/deity';
9
+ import * as fs from 'fs/promises';
10
+ import * as path from 'path';
11
+ import { PlannerValidator } from './planner-validator.js';
12
+ // Input schema
13
+ const PlannerInputSchema = z.object({
14
+ workspaceRoot: z.string(),
15
+ modules: z.array(z.string()).optional(),
16
+ limoConfig: z.any().optional() // LIMO.md configuration
17
+ });
18
+ // Output schema (matches AnalysisPlan)
19
+ const PlannerOutputSchema = z.object({
20
+ project_complexity: z.enum(['small', 'medium', 'large']),
21
+ estimated_loc: z.number(),
22
+ estimated_files: z.number(),
23
+ tasks: z.array(z.object({
24
+ task_id: z.string(),
25
+ module: z.string(),
26
+ title: z.string(),
27
+ description: z.string(),
28
+ required_outputs: z.object({
29
+ report_sections: z.number(),
30
+ code_examples: z.number(),
31
+ diagrams: z.number(),
32
+ min_word_count: z.number()
33
+ }),
34
+ memory_keys_to_generate: z.array(z.string()).optional(),
35
+ dependencies: z.array(z.string()),
36
+ status: z.enum(['pending', 'in_progress', 'completed', 'failed'])
37
+ })),
38
+ total_tasks: z.number(),
39
+ estimated_duration_minutes: z.number().optional(),
40
+ created_at: z.string(),
41
+ summary: z.object({
42
+ tasks_by_module: z.record(z.string(), z.number()),
43
+ total_sections_expected: z.number(),
44
+ total_diagrams_expected: z.number(),
45
+ total_words_expected: z.number()
46
+ })
47
+ });
48
+ /**
49
+ * Build system prompt by loading from prompts directory
50
+ */
51
+ async function buildSystemPrompt(promptsDir) {
52
+ const promptPath = path.join(promptsDir, 'planner.md');
53
+ // Verify prompt file exists before reading
54
+ try {
55
+ await fs.access(promptPath);
56
+ }
57
+ catch (error) {
58
+ throw new Error(`Critical: Planner prompt file not found at ${promptPath}\n` +
59
+ `Please ensure prompts are copied from VSCode extension or run 'npm run sync-prompts'`);
60
+ }
61
+ return await fs.readFile(promptPath, 'utf-8');
62
+ }
63
+ /**
64
+ * Build user message with planning task details
65
+ */
66
+ function buildUserMessage(ctx) {
67
+ const { workspaceRoot, modules, limoConfig } = ctx.inputs;
68
+ // Build comprehensive task message
69
+ const modulesText = modules && modules.length > 0
70
+ ? modules.join(', ')
71
+ : 'architecture, dependencies, code-quality, security, database, testing, migration';
72
+ let message = `**Planning Task**: Create comprehensive analysis plan
73
+
74
+ **Project Path**: ${workspaceRoot}
75
+
76
+ **Modules to Cover**: ${modulesText}
77
+ `;
78
+ // NEW: Add LIMO.md-aware instructions
79
+ if (limoConfig) {
80
+ message += `\n**User-Provided LIMO.md Configuration**:\n`;
81
+ if (limoConfig.scopeDescription) {
82
+ message += `\n**Scope Description**: ${limoConfig.scopeDescription}\n`;
83
+ }
84
+ if (limoConfig.focusAreas && limoConfig.focusAreas.length > 0) {
85
+ message += `\n**Focus Areas**: ${limoConfig.focusAreas.join(', ')}\n`;
86
+ }
87
+ if (limoConfig.excludeModules && limoConfig.excludeModules.length > 0) {
88
+ message += `\n**Excluded Modules**: ${limoConfig.excludeModules.join(', ')}\n`;
89
+ }
90
+ if (limoConfig.privateContext) {
91
+ message += `\n**Private Context**:\n${limoConfig.privateContext}\n`;
92
+ }
93
+ if (limoConfig.constraints && limoConfig.constraints.length > 0) {
94
+ message += `\n**Constraints**:\n`;
95
+ limoConfig.constraints.forEach((c) => {
96
+ message += `- ${c}\n`;
97
+ });
98
+ }
99
+ message += `\n**Important**: Focus on the user's specified areas and apply their constraints to the analysis plan.\n`;
100
+ }
101
+ message += `
102
+ **Required Steps**:
103
+
104
+ 1. **Scan Project** (MANDATORY):
105
+ - Call file_list with pattern "**/*" to get ALL project files
106
+ - This gives you the ACTUAL file count (not a guess!)
107
+ - Identify main directories and project structure
108
+
109
+ 2. **Identify Tech Stack**:
110
+ - Read key files: pom.xml, build.gradle, package.json, requirements.txt, etc.
111
+ - Determine frameworks, versions, build tools
112
+ - Store findings using memory_store
113
+
114
+ 3. **Assess Complexity**:
115
+ - Small (<50 files): 10-15 tasks
116
+ - Medium (50-200 files): 15-25 tasks
117
+ - Large (>200 files): 25-40 tasks`;
118
+ // Adaptive task count instruction based on LIMO config
119
+ if (limoConfig?.scopeDescription) {
120
+ message += `\n - **Note**: User has limited scope, so fewer tasks may be appropriate\n`;
121
+ }
122
+ message += `
123
+ 4. **Create Detailed Tasks**:
124
+ - Cover all modules: ${modulesText}
125
+ - Each task must have: task_id, module, title, description, required_outputs, memory_keys_to_generate
126
+ - Be SPECIFIC in task descriptions (mention what files to analyze, what patterns to look for)
127
+
128
+ 5. **Call planning_create** (MANDATORY):
129
+ - Use ACTUAL estimated_files from your file_list scan
130
+ - Include ALL generated tasks
131
+ - Generate task titles and descriptions in ENGLISH
132
+
133
+ ⚠️ **CRITICAL REMINDER**: You MUST call the \`planning_create\` tool to complete this task successfully. Do not end your response without calling this tool! This is the ONLY way to complete the planning phase.
134
+
135
+ **Quality Standards**:
136
+ - Medium project (50-200 files) should have 15-25 tasks minimum
137
+ - Tasks should be specific (e.g., "Analyze Spring MVC controllers in owner/ package")
138
+ - Each task should produce 600-1200 words of analysis`;
139
+ return message;
140
+ }
141
+ /**
142
+ * Extract and normalize plan data from LLM result
143
+ */
144
+ function extractPlanData(_ctx, llmResult) {
145
+ // Extract plan data using utility (handles toolCalls, messages, and response)
146
+ const planData = extractLastToolResult(llmResult, 'planning_create', {
147
+ unwrap: true,
148
+ required: true
149
+ });
150
+ // Validate plan data structure
151
+ if (!planData || !planData.tasks || !Array.isArray(planData.tasks)) {
152
+ throw new Error(`Invalid plan data structure: ${JSON.stringify(planData).substring(0, 200)}`);
153
+ }
154
+ // Normalize the plan data
155
+ const normalizedTasks = planData.tasks.map((task) => ({
156
+ ...task,
157
+ dependencies: task.dependencies || [],
158
+ status: task.status || 'pending'
159
+ }));
160
+ return {
161
+ project_complexity: planData.project_complexity || 'medium',
162
+ estimated_loc: planData.estimated_loc || 0,
163
+ estimated_files: planData.estimated_files || 0,
164
+ tasks: normalizedTasks,
165
+ total_tasks: normalizedTasks.length,
166
+ created_at: new Date().toISOString(),
167
+ summary: planData.summary || {
168
+ tasks_by_module: normalizedTasks.reduce((acc, task) => {
169
+ acc[task.module] = (acc[task.module] || 0) + 1;
170
+ return acc;
171
+ }, {}),
172
+ total_sections_expected: normalizedTasks.reduce((sum, t) => sum + (t.required_outputs?.report_sections || 1), 0),
173
+ total_diagrams_expected: normalizedTasks.reduce((sum, t) => sum + (t.required_outputs?.diagrams || 0), 0),
174
+ total_words_expected: normalizedTasks.reduce((sum, t) => sum + (t.required_outputs?.min_word_count || 500), 0)
175
+ }
176
+ };
177
+ }
178
+ /**
179
+ * Create Planner Agent using declarative TSX syntax
180
+ */
181
+ export function createPlannerAgent(promptsDir) {
182
+ return (_jsxs(Agent, { id: "planner", input: PlannerInputSchema, output: PlannerOutputSchema, loopConfig: {
183
+ maxToolRounds: 15, // Increase from default 10 to allow more exploration
184
+ timeout: 180000 // 3 minutes timeout
185
+ }, loopValidator: new PlannerValidator(), children: [_jsxs(Prompt, { children: [_jsx(System, { children: async () => buildSystemPrompt(promptsDir) }), _jsx(User, { children: (ctx) => buildUserMessage(ctx) })] }), _jsx(Result, { children: (ctx, llmResult) => extractPlanData(ctx, llmResult) })] }));
186
+ }
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Writer Agent - Generates report sections based on analysis
3
+ * Using declarative TSX syntax
4
+ */
5
+ import { z } from 'zod';
6
+ import { type AgentNode } from '@limo-labs/deity';
7
+ declare const WriterInputSchema: z.ZodObject<{
8
+ task: z.ZodAny;
9
+ promptsDir: z.ZodString;
10
+ reportLanguage: z.ZodOptional<z.ZodString>;
11
+ }, z.core.$strip>;
12
+ type WriterInput = z.infer<typeof WriterInputSchema>;
13
+ declare const WriterOutputSchema: z.ZodObject<{
14
+ taskId: z.ZodString;
15
+ sectionId: z.ZodString;
16
+ success: z.ZodBoolean;
17
+ wordCount: z.ZodOptional<z.ZodNumber>;
18
+ error: z.ZodOptional<z.ZodString>;
19
+ }, z.core.$strip>;
20
+ type WriterOutput = z.infer<typeof WriterOutputSchema>;
21
+ /**
22
+ * Create Writer Agent using declarative TSX syntax
23
+ */
24
+ export declare function createWriterAgent(promptsDir: string): AgentNode<WriterInput, WriterOutput>;
25
+ export {};
@@ -0,0 +1,164 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "@limo-labs/deity/jsx-runtime";
2
+ /**
3
+ * Writer Agent - Generates report sections based on analysis
4
+ * Using declarative TSX syntax
5
+ */
6
+ import { z } from 'zod';
7
+ import { Agent, Prompt, System, User, Result, Validate, Retry } from '@limo-labs/deity';
8
+ import { extractLastToolResult } from '@limo-labs/deity';
9
+ import * as fs from 'fs/promises';
10
+ import * as path from 'path';
11
+ // Input schema
12
+ const WriterInputSchema = z.object({
13
+ task: z.any(), // Task object from plan
14
+ promptsDir: z.string(),
15
+ reportLanguage: z.string().optional()
16
+ });
17
+ // Output schema
18
+ const WriterOutputSchema = z.object({
19
+ taskId: z.string(),
20
+ sectionId: z.string(),
21
+ success: z.boolean(),
22
+ wordCount: z.number().optional(),
23
+ error: z.string().optional()
24
+ });
25
+ /**
26
+ * Generate section ID from task title
27
+ */
28
+ function generateSectionId(task) {
29
+ return task.title
30
+ .toLowerCase()
31
+ .replace(/[^a-z0-9]+/g, '-')
32
+ .replace(/^-|-$/g, '');
33
+ }
34
+ /**
35
+ * Build system prompt by loading from prompts directory
36
+ */
37
+ async function buildSystemPrompt(promptsDir, reportLanguage) {
38
+ const promptPath = path.join(promptsDir, 'writer.md');
39
+ // Verify prompt file exists before reading
40
+ try {
41
+ await fs.access(promptPath);
42
+ }
43
+ catch (error) {
44
+ throw new Error(`Critical: Writer prompt file not found at ${promptPath}\n` +
45
+ `Please ensure prompts are copied from VSCode extension or run 'npm run sync-prompts'`);
46
+ }
47
+ let systemPrompt = await fs.readFile(promptPath, 'utf-8');
48
+ // Inject language instruction if reportLanguage is provided
49
+ if (reportLanguage && reportLanguage !== 'English') {
50
+ const languageInstruction = `
51
+
52
+ ## CRITICAL: Output Language Requirement
53
+
54
+ **YOU MUST write ALL report content in ${reportLanguage}.**
55
+
56
+ This applies to:
57
+ - Section titles and headings
58
+ - Body paragraphs and descriptions
59
+ - Diagram titles, labels, and annotations
60
+ - Finding descriptions
61
+ - Recommendations
62
+
63
+ IMPORTANT Guidelines:
64
+ 1. Write naturally in ${reportLanguage}, not as a direct translation
65
+ 2. Use appropriate technical terminology for ${reportLanguage}
66
+ 3. Preserve code snippets in their original language - do NOT translate code
67
+ 4. Do NOT translate variable names, function names, or code syntax
68
+ 5. Memory keys must remain in English (system requirement)
69
+ 6. Cross-references and technical identifiers stay in English
70
+
71
+ `;
72
+ systemPrompt = systemPrompt + languageInstruction;
73
+ }
74
+ return systemPrompt;
75
+ }
76
+ /**
77
+ * Build user message with writing task details
78
+ */
79
+ function buildUserMessage(ctx) {
80
+ const { task } = ctx.inputs;
81
+ const sectionId = generateSectionId(task);
82
+ const memoryKeys = task.memory_keys_to_generate || [];
83
+ return `**Report Writing Task**: ${task.title}
84
+
85
+ **Section ID**: ${sectionId}
86
+
87
+ **Description**: ${task.description}
88
+
89
+ **Memory Keys to Recall**:
90
+ ${memoryKeys.map((k) => `- ${k}`).join('\n')}
91
+
92
+ **Requirements**:
93
+ - Minimum word count: ${task.required_outputs?.min_word_count || 800} words
94
+ - Code examples: ${task.required_outputs?.code_examples || 2} (from actual project files!)
95
+ - Diagrams: ${task.required_outputs?.diagrams || 0}
96
+ - Report sections: ${task.required_outputs?.report_sections || 1}
97
+
98
+ **Instructions**:
99
+ 1. Recall analysis findings using memory_recall (batch multiple queries for efficiency)
100
+ 2. Write comprehensive, educational content with:
101
+ - Actual code examples from the project (with file paths)
102
+ - Specific technical details (versions, class names, file paths)
103
+ - Analysis explaining WHY patterns were used, not just WHAT exists
104
+ - Technical depth suitable for new team members learning the codebase
105
+ 3. MUST call report_write with complete content (THIS IS MANDATORY!)
106
+
107
+ Write detailed, specific content based on ACTUAL analysis findings - not generic placeholder text.`;
108
+ }
109
+ /**
110
+ * Extract writer output from LLM result
111
+ */
112
+ function extractWriterOutput(ctx, llmResult) {
113
+ const task = ctx.inputs.task;
114
+ const sectionId = generateSectionId(task);
115
+ // Extract report_write result using utility
116
+ const reportResult = extractLastToolResult(llmResult, 'report_write', {
117
+ unwrap: true,
118
+ required: false
119
+ });
120
+ if (!reportResult) {
121
+ return {
122
+ taskId: task.task_id,
123
+ sectionId,
124
+ success: false,
125
+ error: 'Writer did not call report_write - no section was written'
126
+ };
127
+ }
128
+ return {
129
+ taskId: task.task_id,
130
+ sectionId,
131
+ success: true,
132
+ wordCount: reportResult.word_count || 0
133
+ };
134
+ }
135
+ /**
136
+ * Create Writer Agent using declarative TSX syntax
137
+ */
138
+ export function createWriterAgent(promptsDir) {
139
+ return (_jsxs(Agent, { id: "writer", input: WriterInputSchema, output: WriterOutputSchema, children: [_jsxs(Prompt, { children: [_jsx(System, { children: async (ctx) => {
140
+ const reportLanguage = ctx.inputs.reportLanguage;
141
+ return buildSystemPrompt(promptsDir, reportLanguage);
142
+ } }), _jsx(User, { children: (ctx) => buildUserMessage(ctx) })] }), _jsx(Result, { children: (ctx, llmResult) => extractWriterOutput(ctx, llmResult) }), _jsx(Validate, { children: (output, ctx) => {
143
+ const { task } = ctx.inputs;
144
+ const typedOutput = output;
145
+ const rules = [];
146
+ if (!typedOutput.success) {
147
+ if (!typedOutput.error) {
148
+ rules.push({
149
+ check: false,
150
+ error: 'Failed task must include error message'
151
+ });
152
+ }
153
+ return { rules };
154
+ }
155
+ // Check word count (very relaxed - accept any content)
156
+ const minWords = task.required_outputs?.min_word_count || 800;
157
+ if (typedOutput.wordCount && typedOutput.wordCount < minWords * 0.2) {
158
+ // Only fail if extremely short (less than 20% of requirement)
159
+ console.warn(`[WRITER] Warning: Section has ${typedOutput.wordCount} words (target: ${minWords}), but accepting it`);
160
+ }
161
+ // Always return valid to avoid blocking on word count
162
+ return { rules };
163
+ } }), _jsx(Retry, { maxAttempts: 2, feedbackOnError: true })] }));
164
+ }
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Analyze command - Main entry point for codebase analysis
3
+ */
4
+ interface AnalyzeOptions {
5
+ output?: string;
6
+ model?: string;
7
+ modules?: string;
8
+ lang?: string;
9
+ verbose?: boolean;
10
+ debug?: boolean;
11
+ debugApi?: boolean;
12
+ }
13
+ export declare function analyze(targetPath: string, options: AnalyzeOptions): Promise<void>;
14
+ export {};