midas-mcp 4.0.0 → 5.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/analyzer.d.ts.map +1 -1
- package/dist/analyzer.js +70 -22
- package/dist/analyzer.js.map +1 -1
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +185 -2
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts +6 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +38 -0
- package/dist/config.js.map +1 -1
- package/dist/docs/WHY.md +168 -0
- package/dist/docs/examples/brainlift-example.md +87 -0
- package/dist/docs/examples/gameplan-example.md +230 -0
- package/dist/docs/examples/prd-example.md +170 -0
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +32 -2
- package/dist/server.js.map +1 -1
- package/dist/state/phase.d.ts +32 -0
- package/dist/state/phase.d.ts.map +1 -1
- package/dist/state/phase.js +25 -21
- package/dist/state/phase.js.map +1 -1
- package/dist/tools/analyze.d.ts +5 -0
- package/dist/tools/analyze.d.ts.map +1 -1
- package/dist/tools/analyze.js +21 -0
- package/dist/tools/analyze.js.map +1 -1
- package/dist/tools/cleanup.d.ts +53 -0
- package/dist/tools/cleanup.d.ts.map +1 -0
- package/dist/tools/cleanup.js +170 -0
- package/dist/tools/cleanup.js.map +1 -0
- package/dist/tools/examples.d.ts +30 -0
- package/dist/tools/examples.d.ts.map +1 -0
- package/dist/tools/examples.js +65 -0
- package/dist/tools/examples.js.map +1 -0
- package/dist/tools/hotfix.d.ts +69 -0
- package/dist/tools/hotfix.d.ts.map +1 -0
- package/dist/tools/hotfix.js +174 -0
- package/dist/tools/hotfix.js.map +1 -0
- package/dist/tools/index.d.ts +6 -1
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +11 -1
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/scope.d.ts +50 -0
- package/dist/tools/scope.d.ts.map +1 -0
- package/dist/tools/scope.js +277 -0
- package/dist/tools/scope.js.map +1 -0
- package/dist/tools/validate-docs.d.ts +65 -0
- package/dist/tools/validate-docs.d.ts.map +1 -0
- package/dist/tools/validate-docs.js +196 -0
- package/dist/tools/validate-docs.js.map +1 -0
- package/dist/tools/verify.d.ts +22 -0
- package/dist/tools/verify.d.ts.map +1 -1
- package/dist/tools/verify.js +65 -1
- package/dist/tools/verify.js.map +1 -1
- package/dist/tracker.d.ts +36 -0
- package/dist/tracker.d.ts.map +1 -1
- package/dist/tracker.js +134 -0
- package/dist/tracker.js.map +1 -1
- package/dist/tui.d.ts.map +1 -1
- package/dist/tui.js +165 -40
- package/dist/tui.js.map +1 -1
- package/docs/WHY.md +168 -0
- package/docs/examples/brainlift-example.md +87 -0
- package/docs/examples/gameplan-example.md +230 -0
- package/docs/examples/prd-example.md +170 -0
- package/package.json +1 -1
package/dist/tools/analyze.js
CHANGED
|
@@ -2,6 +2,7 @@ import { z } from 'zod';
|
|
|
2
2
|
import { analyzeProject } from '../analyzer.js';
|
|
3
3
|
import { loadState, setPhase, getNextPhase } from '../state/phase.js';
|
|
4
4
|
import { getApiKey } from '../config.js';
|
|
5
|
+
import { validatePlanningDocs } from './validate-docs.js';
|
|
5
6
|
// Tool: midas_analyze - AI-powered project analysis
|
|
6
7
|
export const analyzeSchema = z.object({
|
|
7
8
|
projectPath: z.string().optional().describe('Path to project root'),
|
|
@@ -169,12 +170,32 @@ export function suggestPrompt(input) {
|
|
|
169
170
|
// Tool: midas_advance_phase - Advance to the next step
|
|
170
171
|
export const advancePhaseSchema = z.object({
|
|
171
172
|
projectPath: z.string().optional().describe('Path to project root'),
|
|
173
|
+
force: z.boolean().optional().describe('Force advance even if validation fails'),
|
|
172
174
|
});
|
|
173
175
|
export function advancePhase(input) {
|
|
174
176
|
const projectPath = input.projectPath || process.cwd();
|
|
175
177
|
const state = loadState(projectPath);
|
|
176
178
|
const previous = state.current;
|
|
177
179
|
const next = getNextPhase(previous);
|
|
180
|
+
// Check if advancing from EAGLE_SIGHT (Plan) to BUILD - validate planning docs
|
|
181
|
+
if (previous.phase === 'EAGLE_SIGHT' && next.phase === 'BUILD' && !input.force) {
|
|
182
|
+
const validation = validatePlanningDocs({ projectPath });
|
|
183
|
+
if (!validation.readyForBuild) {
|
|
184
|
+
return {
|
|
185
|
+
previous: {
|
|
186
|
+
phase: previous.phase,
|
|
187
|
+
step: previous.step,
|
|
188
|
+
},
|
|
189
|
+
current: {
|
|
190
|
+
phase: previous.phase,
|
|
191
|
+
step: previous.step,
|
|
192
|
+
},
|
|
193
|
+
message: `Cannot advance to BUILD: planning docs incomplete`,
|
|
194
|
+
blocked: true,
|
|
195
|
+
blockers: validation.blockers,
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
}
|
|
178
199
|
setPhase(projectPath, next);
|
|
179
200
|
const prevStr = previous.phase === 'IDLE'
|
|
180
201
|
? 'IDLE'
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"analyze.js","sourceRoot":"","sources":["../../src/tools/analyze.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,cAAc,EAAwB,MAAM,gBAAgB,CAAC;AACtE,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACtE,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"analyze.js","sourceRoot":"","sources":["../../src/tools/analyze.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export interface DebtItem {
|
|
3
|
+
file: string;
|
|
4
|
+
line: number;
|
|
5
|
+
type: 'TODO' | 'FIXME' | 'HACK' | 'XXX' | 'BUG';
|
|
6
|
+
text: string;
|
|
7
|
+
priority: number;
|
|
8
|
+
}
|
|
9
|
+
export interface CleanupAnalysis {
|
|
10
|
+
totalDebtItems: number;
|
|
11
|
+
debtByType: Record<string, number>;
|
|
12
|
+
topFiles: Array<{
|
|
13
|
+
file: string;
|
|
14
|
+
churn: number;
|
|
15
|
+
debtCount: number;
|
|
16
|
+
}>;
|
|
17
|
+
items: DebtItem[];
|
|
18
|
+
suggestedPrompt: string;
|
|
19
|
+
}
|
|
20
|
+
export declare const scanDebtSchema: z.ZodObject<{
|
|
21
|
+
projectPath: z.ZodOptional<z.ZodString>;
|
|
22
|
+
limit: z.ZodOptional<z.ZodNumber>;
|
|
23
|
+
}, "strip", z.ZodTypeAny, {
|
|
24
|
+
projectPath?: string | undefined;
|
|
25
|
+
limit?: number | undefined;
|
|
26
|
+
}, {
|
|
27
|
+
projectPath?: string | undefined;
|
|
28
|
+
limit?: number | undefined;
|
|
29
|
+
}>;
|
|
30
|
+
export type ScanDebtInput = z.infer<typeof scanDebtSchema>;
|
|
31
|
+
/**
|
|
32
|
+
* Scan codebase for TODO/FIXME/HACK comments
|
|
33
|
+
*/
|
|
34
|
+
export declare function scanDebt(input: ScanDebtInput): CleanupAnalysis;
|
|
35
|
+
export declare const getCleanupSuggestionSchema: z.ZodObject<{
|
|
36
|
+
projectPath: z.ZodOptional<z.ZodString>;
|
|
37
|
+
}, "strip", z.ZodTypeAny, {
|
|
38
|
+
projectPath?: string | undefined;
|
|
39
|
+
}, {
|
|
40
|
+
projectPath?: string | undefined;
|
|
41
|
+
}>;
|
|
42
|
+
export type GetCleanupSuggestionInput = z.infer<typeof getCleanupSuggestionSchema>;
|
|
43
|
+
export interface CleanupSuggestion {
|
|
44
|
+
focus: 'refactor' | 'simplify' | 'document' | 'test';
|
|
45
|
+
target: string;
|
|
46
|
+
reason: string;
|
|
47
|
+
prompt: string;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Get a cleanup-focused suggestion (refactoring, not feature building)
|
|
51
|
+
*/
|
|
52
|
+
export declare function getCleanupSuggestion(input: GetCleanupSuggestionInput): CleanupSuggestion;
|
|
53
|
+
//# sourceMappingURL=cleanup.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cleanup.d.ts","sourceRoot":"","sources":["../../src/tools/cleanup.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAWxB,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,GAAG,OAAO,GAAG,MAAM,GAAG,KAAK,GAAG,KAAK,CAAC;IAChD,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,eAAe;IAC9B,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,QAAQ,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACpE,KAAK,EAAE,QAAQ,EAAE,CAAC;IAClB,eAAe,EAAE,MAAM,CAAC;CACzB;AAMD,eAAO,MAAM,cAAc;;;;;;;;;EAGzB,CAAC;AAEH,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAC;AAU3D;;GAEG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,aAAa,GAAG,eAAe,CA2E9D;AAgED,eAAO,MAAM,0BAA0B;;;;;;EAErC,CAAC;AAEH,MAAM,MAAM,yBAAyB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,0BAA0B,CAAC,CAAC;AAEnF,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,UAAU,GAAG,UAAU,GAAG,UAAU,GAAG,MAAM,CAAC;IACrD,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,yBAAyB,GAAG,iBAAiB,CAsBxF"}
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { existsSync, readFileSync, readdirSync, statSync } from 'fs';
|
|
3
|
+
import { join, relative } from 'path';
|
|
4
|
+
import { execSync } from 'child_process';
|
|
5
|
+
import { sanitizePath, isShellSafe } from '../security.js';
|
|
6
|
+
import { logEvent } from '../events.js';
|
|
7
|
+
// ============================================================================
|
|
8
|
+
// Scan for tech debt markers
|
|
9
|
+
// ============================================================================
|
|
10
|
+
export const scanDebtSchema = z.object({
|
|
11
|
+
projectPath: z.string().optional().describe('Path to project root'),
|
|
12
|
+
limit: z.number().optional().describe('Max items to return (default 20)'),
|
|
13
|
+
});
|
|
14
|
+
const DEBT_PATTERNS = [
|
|
15
|
+
{ pattern: /\/\/\s*(TODO|FIXME|HACK|XXX|BUG):?\s*(.*)$/i, type: 'comment' },
|
|
16
|
+
{ pattern: /#\s*(TODO|FIXME|HACK|XXX|BUG):?\s*(.*)$/i, type: 'hash' },
|
|
17
|
+
];
|
|
18
|
+
const IGNORE_DIRS = ['node_modules', '.git', 'dist', 'build', '.midas', 'coverage'];
|
|
19
|
+
const CODE_EXTENSIONS = ['.ts', '.tsx', '.js', '.jsx', '.py', '.rs', '.go', '.java', '.rb'];
|
|
20
|
+
/**
|
|
21
|
+
* Scan codebase for TODO/FIXME/HACK comments
|
|
22
|
+
*/
|
|
23
|
+
export function scanDebt(input) {
|
|
24
|
+
const projectPath = sanitizePath(input.projectPath);
|
|
25
|
+
const limit = input.limit || 20;
|
|
26
|
+
const items = [];
|
|
27
|
+
const fileChurn = getFileChurn(projectPath);
|
|
28
|
+
function scanDir(dir, depth = 0) {
|
|
29
|
+
if (depth > 10)
|
|
30
|
+
return;
|
|
31
|
+
try {
|
|
32
|
+
const entries = readdirSync(dir);
|
|
33
|
+
for (const entry of entries) {
|
|
34
|
+
if (IGNORE_DIRS.includes(entry))
|
|
35
|
+
continue;
|
|
36
|
+
const fullPath = join(dir, entry);
|
|
37
|
+
try {
|
|
38
|
+
const stat = statSync(fullPath);
|
|
39
|
+
if (stat.isDirectory()) {
|
|
40
|
+
scanDir(fullPath, depth + 1);
|
|
41
|
+
}
|
|
42
|
+
else if (stat.isFile()) {
|
|
43
|
+
const ext = entry.slice(entry.lastIndexOf('.'));
|
|
44
|
+
if (CODE_EXTENSIONS.includes(ext)) {
|
|
45
|
+
scanFile(fullPath, projectPath, items, fileChurn);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
catch { }
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
catch { }
|
|
53
|
+
}
|
|
54
|
+
scanDir(projectPath);
|
|
55
|
+
// Sort by priority (churn-based) and limit
|
|
56
|
+
items.sort((a, b) => b.priority - a.priority);
|
|
57
|
+
const limitedItems = items.slice(0, limit);
|
|
58
|
+
// Aggregate stats
|
|
59
|
+
const debtByType = {};
|
|
60
|
+
for (const item of items) {
|
|
61
|
+
debtByType[item.type] = (debtByType[item.type] || 0) + 1;
|
|
62
|
+
}
|
|
63
|
+
// Top files by debt + churn
|
|
64
|
+
const fileStats = new Map();
|
|
65
|
+
for (const item of items) {
|
|
66
|
+
const existing = fileStats.get(item.file) || { churn: item.priority, debtCount: 0 };
|
|
67
|
+
existing.debtCount++;
|
|
68
|
+
fileStats.set(item.file, existing);
|
|
69
|
+
}
|
|
70
|
+
const topFiles = Array.from(fileStats.entries())
|
|
71
|
+
.map(([file, stats]) => ({ file, ...stats }))
|
|
72
|
+
.sort((a, b) => (b.churn * b.debtCount) - (a.churn * a.debtCount))
|
|
73
|
+
.slice(0, 5);
|
|
74
|
+
// Generate suggested prompt
|
|
75
|
+
let suggestedPrompt = 'No tech debt found. Codebase is clean!';
|
|
76
|
+
if (limitedItems.length > 0) {
|
|
77
|
+
const topItem = limitedItems[0];
|
|
78
|
+
suggestedPrompt = `Address the ${topItem.type} in ${topItem.file}:${topItem.line}: "${topItem.text.slice(0, 50)}..."`;
|
|
79
|
+
}
|
|
80
|
+
logEvent(projectPath, {
|
|
81
|
+
type: 'tool_called',
|
|
82
|
+
tool: 'midas_scan_debt',
|
|
83
|
+
data: { totalItems: items.length },
|
|
84
|
+
});
|
|
85
|
+
return {
|
|
86
|
+
totalDebtItems: items.length,
|
|
87
|
+
debtByType,
|
|
88
|
+
topFiles,
|
|
89
|
+
items: limitedItems,
|
|
90
|
+
suggestedPrompt,
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
function scanFile(filePath, projectPath, items, fileChurn) {
|
|
94
|
+
try {
|
|
95
|
+
const content = readFileSync(filePath, 'utf-8');
|
|
96
|
+
const lines = content.split('\n');
|
|
97
|
+
const relativePath = relative(projectPath, filePath);
|
|
98
|
+
const churn = fileChurn.get(relativePath) || 0;
|
|
99
|
+
for (let i = 0; i < lines.length; i++) {
|
|
100
|
+
const line = lines[i];
|
|
101
|
+
for (const { pattern } of DEBT_PATTERNS) {
|
|
102
|
+
const match = line.match(pattern);
|
|
103
|
+
if (match) {
|
|
104
|
+
items.push({
|
|
105
|
+
file: relativePath,
|
|
106
|
+
line: i + 1,
|
|
107
|
+
type: match[1].toUpperCase(),
|
|
108
|
+
text: match[2]?.trim() || '',
|
|
109
|
+
priority: churn,
|
|
110
|
+
});
|
|
111
|
+
break; // Only one match per line
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
catch { }
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Get file churn (number of commits that touched each file)
|
|
120
|
+
*/
|
|
121
|
+
function getFileChurn(projectPath) {
|
|
122
|
+
const churn = new Map();
|
|
123
|
+
if (!existsSync(join(projectPath, '.git')))
|
|
124
|
+
return churn;
|
|
125
|
+
if (!isShellSafe(projectPath))
|
|
126
|
+
return churn;
|
|
127
|
+
try {
|
|
128
|
+
// Get commit counts per file (last 100 commits for performance)
|
|
129
|
+
const output = execSync('git log --name-only --pretty=format: -100 | sort | uniq -c | sort -rn | head -50', { cwd: projectPath, encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] });
|
|
130
|
+
for (const line of output.split('\n')) {
|
|
131
|
+
const match = line.trim().match(/^\s*(\d+)\s+(.+)$/);
|
|
132
|
+
if (match) {
|
|
133
|
+
churn.set(match[2], parseInt(match[1]));
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
catch { }
|
|
138
|
+
return churn;
|
|
139
|
+
}
|
|
140
|
+
// ============================================================================
|
|
141
|
+
// Get cleanup suggestions
|
|
142
|
+
// ============================================================================
|
|
143
|
+
export const getCleanupSuggestionSchema = z.object({
|
|
144
|
+
projectPath: z.string().optional().describe('Path to project root'),
|
|
145
|
+
});
|
|
146
|
+
/**
|
|
147
|
+
* Get a cleanup-focused suggestion (refactoring, not feature building)
|
|
148
|
+
*/
|
|
149
|
+
export function getCleanupSuggestion(input) {
|
|
150
|
+
const projectPath = sanitizePath(input.projectPath);
|
|
151
|
+
const debt = scanDebt({ projectPath, limit: 10 });
|
|
152
|
+
// If there's debt, suggest addressing it
|
|
153
|
+
if (debt.items.length > 0) {
|
|
154
|
+
const topItem = debt.items[0];
|
|
155
|
+
return {
|
|
156
|
+
focus: 'refactor',
|
|
157
|
+
target: `${topItem.file}:${topItem.line}`,
|
|
158
|
+
reason: `High-churn file with ${topItem.type} marker`,
|
|
159
|
+
prompt: `Refactor ${topItem.file}:${topItem.line} to address: ${topItem.text}. Keep changes minimal and focused.`,
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
// Otherwise, suggest test coverage or docs
|
|
163
|
+
return {
|
|
164
|
+
focus: 'test',
|
|
165
|
+
target: 'test coverage',
|
|
166
|
+
reason: 'No tech debt markers found',
|
|
167
|
+
prompt: 'Review test coverage. Add tests for any uncovered edge cases in the most complex functions.',
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
//# sourceMappingURL=cleanup.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cleanup.js","sourceRoot":"","sources":["../../src/tools/cleanup.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,IAAI,CAAC;AACrE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,MAAM,CAAC;AACtC,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC3D,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAsBxC,+EAA+E;AAC/E,6BAA6B;AAC7B,+EAA+E;AAE/E,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,CAAC,MAAM,CAAC;IACrC,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,sBAAsB,CAAC;IACnE,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,kCAAkC,CAAC;CAC1E,CAAC,CAAC;AAIH,MAAM,aAAa,GAAG;IACpB,EAAE,OAAO,EAAE,6CAA6C,EAAE,IAAI,EAAE,SAAS,EAAE;IAC3E,EAAE,OAAO,EAAE,0CAA0C,EAAE,IAAI,EAAE,MAAM,EAAE;CACtE,CAAC;AAEF,MAAM,WAAW,GAAG,CAAC,cAAc,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,UAAU,CAAC,CAAC;AACpF,MAAM,eAAe,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,CAAC,CAAC;AAE5F;;GAEG;AACH,MAAM,UAAU,QAAQ,CAAC,KAAoB;IAC3C,MAAM,WAAW,GAAG,YAAY,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;IACpD,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,IAAI,EAAE,CAAC;IAEhC,MAAM,KAAK,GAAe,EAAE,CAAC;IAC7B,MAAM,SAAS,GAAG,YAAY,CAAC,WAAW,CAAC,CAAC;IAE5C,SAAS,OAAO,CAAC,GAAW,EAAE,KAAK,GAAG,CAAC;QACrC,IAAI,KAAK,GAAG,EAAE;YAAE,OAAO;QAEvB,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC;YACjC,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;gBAC5B,IAAI,WAAW,CAAC,QAAQ,CAAC,KAAK,CAAC;oBAAE,SAAS;gBAE1C,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;gBAClC,IAAI,CAAC;oBACH,MAAM,IAAI,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAC;oBAChC,IAAI,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC;wBACvB,OAAO,CAAC,QAAQ,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC;oBAC/B,CAAC;yBAAM,IAAI,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC;wBACzB,MAAM,GAAG,GAAG,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC;wBAChD,IAAI,eAAe,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;4BAClC,QAAQ,CAAC,QAAQ,EAAE,WAAW,EAAE,KAAK,EAAE,SAAS,CAAC,CAAC;wBACpD,CAAC;oBACH,CAAC;gBACH,CAAC;gBAAC,MAAM,CAAC,CAAA,CAAC;YACZ,CAAC;QACH,CAAC;QAAC,MAAM,CAAC,CAAA,CAAC;IACZ,CAAC;IAED,OAAO,CAAC,WAAW,CAAC,CAAC;IAErB,2CAA2C;IAC3C,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC;IAC9C,MAAM,YAAY,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;IAE3C,kBAAkB;IAClB,MAAM,UAAU,GAA2B,EAAE,CAAC;IAC9C,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;IAC3D,CAAC;IAED,4BAA4B;IAC5B,MAAM,SAAS,GAAG,IAAI,GAAG,EAAgD,CAAC;IAC1E,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,QAAQ,GAAG,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,IAAI,CAAC,QAAQ,EAAE,SAAS,EAAE,CAAC,EAAE,CAAC;QACpF,QAAQ,CAAC,SAAS,EAAE,CAAC;QACrB,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IACrC,CAAC;IACD,MAAM,QAAQ,GAAG,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,CAAC;SAC7C,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,GAAG,KAAK,EAAE,CAAC,CAAC;SAC5C,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,SAAS,CAAC,CAAC;SACjE,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAEf,4BAA4B;IAC5B,IAAI,eAAe,GAAG,wCAAwC,CAAC;IAC/D,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC5B,MAAM,OAAO,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC;QAChC,eAAe,GAAG,eAAe,OAAO,CAAC,IAAI,OAAO,OAAO,CAAC,IAAI,IAAI,OAAO,CAAC,IAAI,MAAM,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC;IACxH,CAAC;IAED,QAAQ,CAAC,WAAW,EAAE;QACpB,IAAI,EAAE,aAAa;QACnB,IAAI,EAAE,iBAAiB;QACvB,IAAI,EAAE,EAAE,UAAU,EAAE,KAAK,CAAC,MAAM,EAAE;KACnC,CAAC,CAAC;IAEH,OAAO;QACL,cAAc,EAAE,KAAK,CAAC,MAAM;QAC5B,UAAU;QACV,QAAQ;QACR,KAAK,EAAE,YAAY;QACnB,eAAe;KAChB,CAAC;AACJ,CAAC;AAED,SAAS,QAAQ,CACf,QAAgB,EAChB,WAAmB,EACnB,KAAiB,EACjB,SAA8B;IAE9B,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QAChD,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAClC,MAAM,YAAY,GAAG,QAAQ,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;QACrD,MAAM,KAAK,GAAG,SAAS,CAAC,GAAG,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;QAE/C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACtC,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;YACtB,KAAK,MAAM,EAAE,OAAO,EAAE,IAAI,aAAa,EAAE,CAAC;gBACxC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;gBAClC,IAAI,KAAK,EAAE,CAAC;oBACV,KAAK,CAAC,IAAI,CAAC;wBACT,IAAI,EAAE,YAAY;wBAClB,IAAI,EAAE,CAAC,GAAG,CAAC;wBACX,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,WAAW,EAAsB;wBAChD,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE;wBAC5B,QAAQ,EAAE,KAAK;qBAChB,CAAC,CAAC;oBACH,MAAM,CAAE,0BAA0B;gBACpC,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAAC,MAAM,CAAC,CAAA,CAAC;AACZ,CAAC;AAED;;GAEG;AACH,SAAS,YAAY,CAAC,WAAmB;IACvC,MAAM,KAAK,GAAG,IAAI,GAAG,EAAkB,CAAC;IAExC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;QAAE,OAAO,KAAK,CAAC;IACzD,IAAI,CAAC,WAAW,CAAC,WAAW,CAAC;QAAE,OAAO,KAAK,CAAC;IAE5C,IAAI,CAAC;QACH,gEAAgE;QAChE,MAAM,MAAM,GAAG,QAAQ,CACrB,kFAAkF,EAClF,EAAE,GAAG,EAAE,WAAW,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,CACzE,CAAC;QAEF,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;YACtC,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,mBAAmB,CAAC,CAAC;YACrD,IAAI,KAAK,EAAE,CAAC;gBACV,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YAC1C,CAAC;QACH,CAAC;IACH,CAAC;IAAC,MAAM,CAAC,CAAA,CAAC;IAEV,OAAO,KAAK,CAAC;AACf,CAAC;AAED,+EAA+E;AAC/E,0BAA0B;AAC1B,+EAA+E;AAE/E,MAAM,CAAC,MAAM,0BAA0B,GAAG,CAAC,CAAC,MAAM,CAAC;IACjD,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,sBAAsB,CAAC;CACpE,CAAC,CAAC;AAWH;;GAEG;AACH,MAAM,UAAU,oBAAoB,CAAC,KAAgC;IACnE,MAAM,WAAW,GAAG,YAAY,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;IACpD,MAAM,IAAI,GAAG,QAAQ,CAAC,EAAE,WAAW,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,CAAC;IAElD,yCAAyC;IACzC,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC1B,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QAC9B,OAAO;YACL,KAAK,EAAE,UAAU;YACjB,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,IAAI,OAAO,CAAC,IAAI,EAAE;YACzC,MAAM,EAAE,wBAAwB,OAAO,CAAC,IAAI,SAAS;YACrD,MAAM,EAAE,YAAY,OAAO,CAAC,IAAI,IAAI,OAAO,CAAC,IAAI,gBAAgB,OAAO,CAAC,IAAI,qCAAqC;SAClH,CAAC;IACJ,CAAC;IAED,2CAA2C;IAC3C,OAAO;QACL,KAAK,EAAE,MAAM;QACb,MAAM,EAAE,eAAe;QACvB,MAAM,EAAE,4BAA4B;QACpC,MAAM,EAAE,6FAA6F;KACtG,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export declare const showExampleSchema: z.ZodObject<{
|
|
3
|
+
step: z.ZodOptional<z.ZodString>;
|
|
4
|
+
projectPath: z.ZodOptional<z.ZodString>;
|
|
5
|
+
}, "strip", z.ZodTypeAny, {
|
|
6
|
+
step?: string | undefined;
|
|
7
|
+
projectPath?: string | undefined;
|
|
8
|
+
}, {
|
|
9
|
+
step?: string | undefined;
|
|
10
|
+
projectPath?: string | undefined;
|
|
11
|
+
}>;
|
|
12
|
+
export type ShowExampleInput = z.infer<typeof showExampleSchema>;
|
|
13
|
+
export interface ShowExampleResult {
|
|
14
|
+
step: string;
|
|
15
|
+
exampleFile: string;
|
|
16
|
+
content: string;
|
|
17
|
+
summary: string;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Get the example document for a given step
|
|
21
|
+
*/
|
|
22
|
+
export declare function showExample(input: ShowExampleInput): ShowExampleResult;
|
|
23
|
+
/**
|
|
24
|
+
* Get available examples
|
|
25
|
+
*/
|
|
26
|
+
export declare function listExamples(): {
|
|
27
|
+
step: string;
|
|
28
|
+
file: string;
|
|
29
|
+
}[];
|
|
30
|
+
//# sourceMappingURL=examples.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"examples.d.ts","sourceRoot":"","sources":["../../src/tools/examples.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAgBxB,eAAO,MAAM,iBAAiB;;;;;;;;;EAG5B,CAAC;AAEH,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAEjE,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,gBAAgB,GAAG,iBAAiB,CAqCtE;AAED;;GAEG;AACH,wBAAgB,YAAY,IAAI;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,EAAE,CAK/D"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from 'fs';
|
|
2
|
+
import { join, dirname } from 'path';
|
|
3
|
+
import { fileURLToPath } from 'url';
|
|
4
|
+
import { z } from 'zod';
|
|
5
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
6
|
+
const __dirname = dirname(__filename);
|
|
7
|
+
// Map steps to their example documents
|
|
8
|
+
const STEP_EXAMPLES = {
|
|
9
|
+
// PLAN phase steps
|
|
10
|
+
BRAINLIFT: 'brainlift-example.md',
|
|
11
|
+
PRD: 'prd-example.md',
|
|
12
|
+
GAMEPLAN: 'gameplan-example.md',
|
|
13
|
+
// Other steps use nearest relevant example
|
|
14
|
+
IDEA: 'brainlift-example.md',
|
|
15
|
+
RESEARCH: 'brainlift-example.md',
|
|
16
|
+
};
|
|
17
|
+
export const showExampleSchema = z.object({
|
|
18
|
+
step: z.string().optional().describe('Step to show example for: BRAINLIFT, PRD, or GAMEPLAN'),
|
|
19
|
+
projectPath: z.string().optional().describe('Path to project root'),
|
|
20
|
+
});
|
|
21
|
+
/**
|
|
22
|
+
* Get the example document for a given step
|
|
23
|
+
*/
|
|
24
|
+
export function showExample(input) {
|
|
25
|
+
const step = (input.step || 'BRAINLIFT').toUpperCase();
|
|
26
|
+
// Find the example file for this step
|
|
27
|
+
const exampleFileName = STEP_EXAMPLES[step] || 'brainlift-example.md';
|
|
28
|
+
// Look for example in docs/examples/
|
|
29
|
+
const docsPath = join(__dirname, '..', 'docs', 'examples', exampleFileName);
|
|
30
|
+
if (!existsSync(docsPath)) {
|
|
31
|
+
return {
|
|
32
|
+
step,
|
|
33
|
+
exampleFile: exampleFileName,
|
|
34
|
+
content: `Example file not found: ${exampleFileName}`,
|
|
35
|
+
summary: 'No example available for this step.',
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
const content = readFileSync(docsPath, 'utf-8');
|
|
39
|
+
// Extract first paragraph after the title as summary
|
|
40
|
+
const lines = content.split('\n');
|
|
41
|
+
let summary = '';
|
|
42
|
+
for (let i = 0; i < lines.length; i++) {
|
|
43
|
+
const line = lines[i].trim();
|
|
44
|
+
if (line && !line.startsWith('#') && !line.startsWith('---')) {
|
|
45
|
+
summary = line.slice(0, 100) + (line.length > 100 ? '...' : '');
|
|
46
|
+
break;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return {
|
|
50
|
+
step,
|
|
51
|
+
exampleFile: exampleFileName,
|
|
52
|
+
content,
|
|
53
|
+
summary: summary || 'Example document for ' + step,
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Get available examples
|
|
58
|
+
*/
|
|
59
|
+
export function listExamples() {
|
|
60
|
+
return Object.entries(STEP_EXAMPLES).map(([step, file]) => ({
|
|
61
|
+
step,
|
|
62
|
+
file,
|
|
63
|
+
}));
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=examples.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"examples.js","sourceRoot":"","sources":["../../src/tools/examples.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,IAAI,CAAC;AAC9C,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AACrC,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AACpC,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;AAEtC,uCAAuC;AACvC,MAAM,aAAa,GAA2B;IAC5C,mBAAmB;IACnB,SAAS,EAAE,sBAAsB;IACjC,GAAG,EAAE,gBAAgB;IACrB,QAAQ,EAAE,qBAAqB;IAC/B,2CAA2C;IAC3C,IAAI,EAAE,sBAAsB;IAC5B,QAAQ,EAAE,sBAAsB;CACjC,CAAC;AAEF,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,CAAC,MAAM,CAAC;IACxC,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,uDAAuD,CAAC;IAC7F,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,sBAAsB,CAAC;CACpE,CAAC,CAAC;AAWH;;GAEG;AACH,MAAM,UAAU,WAAW,CAAC,KAAuB;IACjD,MAAM,IAAI,GAAG,CAAC,KAAK,CAAC,IAAI,IAAI,WAAW,CAAC,CAAC,WAAW,EAAE,CAAC;IAEvD,sCAAsC;IACtC,MAAM,eAAe,GAAG,aAAa,CAAC,IAAI,CAAC,IAAI,sBAAsB,CAAC;IAEtE,qCAAqC;IACrC,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,eAAe,CAAC,CAAC;IAE5E,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC1B,OAAO;YACL,IAAI;YACJ,WAAW,EAAE,eAAe;YAC5B,OAAO,EAAE,2BAA2B,eAAe,EAAE;YACrD,OAAO,EAAE,qCAAqC;SAC/C,CAAC;IACJ,CAAC;IAED,MAAM,OAAO,GAAG,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAEhD,qDAAqD;IACrD,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAClC,IAAI,OAAO,GAAG,EAAE,CAAC;IACjB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACtC,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QAC7B,IAAI,IAAI,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;YAC7D,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YAChE,MAAM;QACR,CAAC;IACH,CAAC;IAED,OAAO;QACL,IAAI;QACJ,WAAW,EAAE,eAAe;QAC5B,OAAO;QACP,OAAO,EAAE,OAAO,IAAI,uBAAuB,GAAG,IAAI;KACnD,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,YAAY;IAC1B,OAAO,MAAM,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC;QAC1D,IAAI;QACJ,IAAI;KACL,CAAC,CAAC,CAAC;AACN,CAAC"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export declare const startHotfixSchema: z.ZodObject<{
|
|
3
|
+
projectPath: z.ZodOptional<z.ZodString>;
|
|
4
|
+
description: z.ZodString;
|
|
5
|
+
}, "strip", z.ZodTypeAny, {
|
|
6
|
+
description: string;
|
|
7
|
+
projectPath?: string | undefined;
|
|
8
|
+
}, {
|
|
9
|
+
description: string;
|
|
10
|
+
projectPath?: string | undefined;
|
|
11
|
+
}>;
|
|
12
|
+
export type StartHotfixInput = z.infer<typeof startHotfixSchema>;
|
|
13
|
+
export interface StartHotfixResult {
|
|
14
|
+
success: boolean;
|
|
15
|
+
previousPhase: string;
|
|
16
|
+
message: string;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Start hotfix mode - saves current phase and jumps to BUILD/DEBUG
|
|
20
|
+
*/
|
|
21
|
+
export declare function startHotfix(input: StartHotfixInput): StartHotfixResult;
|
|
22
|
+
export declare const completeHotfixSchema: z.ZodObject<{
|
|
23
|
+
projectPath: z.ZodOptional<z.ZodString>;
|
|
24
|
+
summary: z.ZodOptional<z.ZodString>;
|
|
25
|
+
}, "strip", z.ZodTypeAny, {
|
|
26
|
+
projectPath?: string | undefined;
|
|
27
|
+
summary?: string | undefined;
|
|
28
|
+
}, {
|
|
29
|
+
projectPath?: string | undefined;
|
|
30
|
+
summary?: string | undefined;
|
|
31
|
+
}>;
|
|
32
|
+
export type CompleteHotfixInput = z.infer<typeof completeHotfixSchema>;
|
|
33
|
+
export interface CompleteHotfixResult {
|
|
34
|
+
success: boolean;
|
|
35
|
+
returnedTo: string;
|
|
36
|
+
message: string;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Complete hotfix mode - return to previous phase
|
|
40
|
+
*/
|
|
41
|
+
export declare function completeHotfix(input: CompleteHotfixInput): CompleteHotfixResult;
|
|
42
|
+
export declare const cancelHotfixSchema: z.ZodObject<{
|
|
43
|
+
projectPath: z.ZodOptional<z.ZodString>;
|
|
44
|
+
reason: z.ZodOptional<z.ZodString>;
|
|
45
|
+
}, "strip", z.ZodTypeAny, {
|
|
46
|
+
projectPath?: string | undefined;
|
|
47
|
+
reason?: string | undefined;
|
|
48
|
+
}, {
|
|
49
|
+
projectPath?: string | undefined;
|
|
50
|
+
reason?: string | undefined;
|
|
51
|
+
}>;
|
|
52
|
+
export type CancelHotfixInput = z.infer<typeof cancelHotfixSchema>;
|
|
53
|
+
export declare function cancelHotfix(input: CancelHotfixInput): CompleteHotfixResult;
|
|
54
|
+
export declare const getHotfixStatusSchema: z.ZodObject<{
|
|
55
|
+
projectPath: z.ZodOptional<z.ZodString>;
|
|
56
|
+
}, "strip", z.ZodTypeAny, {
|
|
57
|
+
projectPath?: string | undefined;
|
|
58
|
+
}, {
|
|
59
|
+
projectPath?: string | undefined;
|
|
60
|
+
}>;
|
|
61
|
+
export type GetHotfixStatusInput = z.infer<typeof getHotfixStatusSchema>;
|
|
62
|
+
export interface HotfixStatus {
|
|
63
|
+
active: boolean;
|
|
64
|
+
description?: string;
|
|
65
|
+
previousPhase?: string;
|
|
66
|
+
duration?: string;
|
|
67
|
+
}
|
|
68
|
+
export declare function getHotfixStatus(input: GetHotfixStatusInput): HotfixStatus;
|
|
69
|
+
//# sourceMappingURL=hotfix.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hotfix.d.ts","sourceRoot":"","sources":["../../src/tools/hotfix.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAUxB,eAAO,MAAM,iBAAiB;;;;;;;;;EAG5B,CAAC;AAEH,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAEjE,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,OAAO,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,gBAAgB,GAAG,iBAAiB,CA8CtE;AAMD,eAAO,MAAM,oBAAoB;;;;;;;;;EAG/B,CAAC;AAEH,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAEvE,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,mBAAmB,GAAG,oBAAoB,CAwC/E;AAMD,eAAO,MAAM,kBAAkB;;;;;;;;;EAG7B,CAAC;AAEH,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAEnE,wBAAgB,YAAY,CAAC,KAAK,EAAE,iBAAiB,GAAG,oBAAoB,CA8B3E;AAMD,eAAO,MAAM,qBAAqB;;;;;;EAEhC,CAAC;AAEH,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAEzE,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,OAAO,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,oBAAoB,GAAG,YAAY,CA4BzE"}
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { loadState, saveState } from '../state/phase.js';
|
|
3
|
+
import { saveToJournal } from './journal.js';
|
|
4
|
+
import { sanitizePath } from '../security.js';
|
|
5
|
+
import { logEvent } from '../events.js';
|
|
6
|
+
// ============================================================================
|
|
7
|
+
// Hotfix Mode - Emergency bug fixes without disrupting normal workflow
|
|
8
|
+
// ============================================================================
|
|
9
|
+
export const startHotfixSchema = z.object({
|
|
10
|
+
projectPath: z.string().optional().describe('Path to project root'),
|
|
11
|
+
description: z.string().describe('Brief description of the bug being fixed'),
|
|
12
|
+
});
|
|
13
|
+
/**
|
|
14
|
+
* Start hotfix mode - saves current phase and jumps to BUILD/DEBUG
|
|
15
|
+
*/
|
|
16
|
+
export function startHotfix(input) {
|
|
17
|
+
const projectPath = sanitizePath(input.projectPath);
|
|
18
|
+
const state = loadState(projectPath);
|
|
19
|
+
// Check if already in hotfix mode
|
|
20
|
+
if (state.hotfix?.active) {
|
|
21
|
+
return {
|
|
22
|
+
success: false,
|
|
23
|
+
previousPhase: formatPhase(state.current),
|
|
24
|
+
message: 'Already in hotfix mode. Complete or cancel the current hotfix first.',
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
// Save current phase and enter hotfix mode
|
|
28
|
+
const previousPhase = state.current;
|
|
29
|
+
state.hotfix = {
|
|
30
|
+
active: true,
|
|
31
|
+
description: input.description,
|
|
32
|
+
previousPhase,
|
|
33
|
+
startedAt: new Date().toISOString(),
|
|
34
|
+
};
|
|
35
|
+
// Jump to BUILD/DEBUG step
|
|
36
|
+
state.current = { phase: 'BUILD', step: 'DEBUG' };
|
|
37
|
+
state.history.push(previousPhase);
|
|
38
|
+
saveState(projectPath, state);
|
|
39
|
+
// Auto-create minimal journal entry
|
|
40
|
+
saveToJournal({
|
|
41
|
+
projectPath,
|
|
42
|
+
title: `HOTFIX: ${input.description}`,
|
|
43
|
+
conversation: `Starting hotfix for: ${input.description}\n\nPrevious phase: ${formatPhase(previousPhase)}\nJumping to BUILD/DEBUG mode.`,
|
|
44
|
+
tags: ['hotfix', 'bug'],
|
|
45
|
+
});
|
|
46
|
+
logEvent(projectPath, {
|
|
47
|
+
type: 'tool_called',
|
|
48
|
+
tool: 'midas_start_hotfix',
|
|
49
|
+
data: { description: input.description, previousPhase: formatPhase(previousPhase) },
|
|
50
|
+
});
|
|
51
|
+
return {
|
|
52
|
+
success: true,
|
|
53
|
+
previousPhase: formatPhase(previousPhase),
|
|
54
|
+
message: `Hotfix mode started. Jumped to BUILD/DEBUG. When complete, use midas_complete_hotfix to return to ${formatPhase(previousPhase)}.`,
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
// ============================================================================
|
|
58
|
+
// Complete Hotfix - Return to previous phase
|
|
59
|
+
// ============================================================================
|
|
60
|
+
export const completeHotfixSchema = z.object({
|
|
61
|
+
projectPath: z.string().optional().describe('Path to project root'),
|
|
62
|
+
summary: z.string().optional().describe('Brief summary of what was fixed'),
|
|
63
|
+
});
|
|
64
|
+
/**
|
|
65
|
+
* Complete hotfix mode - return to previous phase
|
|
66
|
+
*/
|
|
67
|
+
export function completeHotfix(input) {
|
|
68
|
+
const projectPath = sanitizePath(input.projectPath);
|
|
69
|
+
const state = loadState(projectPath);
|
|
70
|
+
// Check if in hotfix mode
|
|
71
|
+
if (!state.hotfix?.active) {
|
|
72
|
+
return {
|
|
73
|
+
success: false,
|
|
74
|
+
returnedTo: formatPhase(state.current),
|
|
75
|
+
message: 'Not in hotfix mode.',
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
const hotfixDescription = state.hotfix.description || 'Unknown hotfix';
|
|
79
|
+
const previousPhase = state.hotfix.previousPhase || { phase: 'IDLE' };
|
|
80
|
+
// Return to previous phase
|
|
81
|
+
state.current = previousPhase;
|
|
82
|
+
state.hotfix = { active: false };
|
|
83
|
+
saveState(projectPath, state);
|
|
84
|
+
// Log completion in journal
|
|
85
|
+
saveToJournal({
|
|
86
|
+
projectPath,
|
|
87
|
+
title: `HOTFIX COMPLETE: ${hotfixDescription}`,
|
|
88
|
+
conversation: `Hotfix completed: ${hotfixDescription}\n\nSummary: ${input.summary || 'No summary provided'}\n\nReturning to: ${formatPhase(previousPhase)}`,
|
|
89
|
+
tags: ['hotfix', 'complete'],
|
|
90
|
+
});
|
|
91
|
+
logEvent(projectPath, {
|
|
92
|
+
type: 'tool_called',
|
|
93
|
+
tool: 'midas_complete_hotfix',
|
|
94
|
+
data: { summary: input.summary, returnedTo: formatPhase(previousPhase) },
|
|
95
|
+
});
|
|
96
|
+
return {
|
|
97
|
+
success: true,
|
|
98
|
+
returnedTo: formatPhase(previousPhase),
|
|
99
|
+
message: `Hotfix complete! Returned to ${formatPhase(previousPhase)}.`,
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
// ============================================================================
|
|
103
|
+
// Cancel Hotfix - Abandon hotfix and return to previous phase
|
|
104
|
+
// ============================================================================
|
|
105
|
+
export const cancelHotfixSchema = z.object({
|
|
106
|
+
projectPath: z.string().optional().describe('Path to project root'),
|
|
107
|
+
reason: z.string().optional().describe('Why the hotfix was cancelled'),
|
|
108
|
+
});
|
|
109
|
+
export function cancelHotfix(input) {
|
|
110
|
+
const projectPath = sanitizePath(input.projectPath);
|
|
111
|
+
const state = loadState(projectPath);
|
|
112
|
+
if (!state.hotfix?.active) {
|
|
113
|
+
return {
|
|
114
|
+
success: false,
|
|
115
|
+
returnedTo: formatPhase(state.current),
|
|
116
|
+
message: 'Not in hotfix mode.',
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
const previousPhase = state.hotfix.previousPhase || { phase: 'IDLE' };
|
|
120
|
+
// Return to previous phase without completion
|
|
121
|
+
state.current = previousPhase;
|
|
122
|
+
state.hotfix = { active: false };
|
|
123
|
+
saveState(projectPath, state);
|
|
124
|
+
logEvent(projectPath, {
|
|
125
|
+
type: 'tool_called',
|
|
126
|
+
tool: 'midas_cancel_hotfix',
|
|
127
|
+
data: { reason: input.reason, returnedTo: formatPhase(previousPhase) },
|
|
128
|
+
});
|
|
129
|
+
return {
|
|
130
|
+
success: true,
|
|
131
|
+
returnedTo: formatPhase(previousPhase),
|
|
132
|
+
message: `Hotfix cancelled. Returned to ${formatPhase(previousPhase)}.`,
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
// ============================================================================
|
|
136
|
+
// Get Hotfix Status
|
|
137
|
+
// ============================================================================
|
|
138
|
+
export const getHotfixStatusSchema = z.object({
|
|
139
|
+
projectPath: z.string().optional().describe('Path to project root'),
|
|
140
|
+
});
|
|
141
|
+
export function getHotfixStatus(input) {
|
|
142
|
+
const projectPath = sanitizePath(input.projectPath);
|
|
143
|
+
const state = loadState(projectPath);
|
|
144
|
+
if (!state.hotfix?.active) {
|
|
145
|
+
return { active: false };
|
|
146
|
+
}
|
|
147
|
+
// Calculate duration
|
|
148
|
+
let duration;
|
|
149
|
+
if (state.hotfix.startedAt) {
|
|
150
|
+
const started = new Date(state.hotfix.startedAt).getTime();
|
|
151
|
+
const now = Date.now();
|
|
152
|
+
const minutes = Math.floor((now - started) / (1000 * 60));
|
|
153
|
+
if (minutes < 60) {
|
|
154
|
+
duration = `${minutes}m`;
|
|
155
|
+
}
|
|
156
|
+
else {
|
|
157
|
+
const hours = Math.floor(minutes / 60);
|
|
158
|
+
duration = `${hours}h ${minutes % 60}m`;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
return {
|
|
162
|
+
active: true,
|
|
163
|
+
description: state.hotfix.description,
|
|
164
|
+
previousPhase: state.hotfix.previousPhase ? formatPhase(state.hotfix.previousPhase) : undefined,
|
|
165
|
+
duration,
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
// Helper function
|
|
169
|
+
function formatPhase(phase) {
|
|
170
|
+
if (phase.phase === 'IDLE')
|
|
171
|
+
return 'IDLE';
|
|
172
|
+
return `${phase.phase}:${phase.step}`;
|
|
173
|
+
}
|
|
174
|
+
//# sourceMappingURL=hotfix.js.map
|