strikethroo 3.0.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.
- package/LICENSE +21 -0
- package/README.md +79 -0
- package/dist/cli.d.ts +9 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +187 -0
- package/dist/cli.js.map +1 -0
- package/dist/conflict-detector.d.ts +24 -0
- package/dist/conflict-detector.d.ts.map +1 -0
- package/dist/conflict-detector.js +130 -0
- package/dist/conflict-detector.js.map +1 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +344 -0
- package/dist/index.js.map +1 -0
- package/dist/metadata.d.ts +40 -0
- package/dist/metadata.d.ts.map +1 -0
- package/dist/metadata.js +121 -0
- package/dist/metadata.js.map +1 -0
- package/dist/plan-utils.d.ts +35 -0
- package/dist/plan-utils.d.ts.map +1 -0
- package/dist/plan-utils.js +123 -0
- package/dist/plan-utils.js.map +1 -0
- package/dist/plan.d.ts +27 -0
- package/dist/plan.d.ts.map +1 -0
- package/dist/plan.js +279 -0
- package/dist/plan.js.map +1 -0
- package/dist/prompts.d.ts +21 -0
- package/dist/prompts.d.ts.map +1 -0
- package/dist/prompts.js +132 -0
- package/dist/prompts.js.map +1 -0
- package/dist/status.d.ts +73 -0
- package/dist/status.d.ts.map +1 -0
- package/dist/status.js +375 -0
- package/dist/status.js.map +1 -0
- package/dist/types.d.ts +274 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +9 -0
- package/dist/types.js.map +1 -0
- package/dist/utils.d.ts +53 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +158 -0
- package/dist/utils.js.map +1 -0
- package/package.json +94 -0
- package/templates/harness/agents/plan-creator.md +95 -0
- package/templates/harness/skills/st-create-plan/SKILL.md +120 -0
- package/templates/harness/skills/st-create-plan/scripts/find-strikethroo-root.cjs +116 -0
- package/templates/harness/skills/st-create-plan/scripts/get-next-plan-id.cjs +197 -0
- package/templates/harness/skills/st-execute-blueprint/SKILL.md +147 -0
- package/templates/harness/skills/st-execute-blueprint/scripts/create-feature-branch.cjs +359 -0
- package/templates/harness/skills/st-execute-blueprint/scripts/find-strikethroo-root.cjs +116 -0
- package/templates/harness/skills/st-execute-blueprint/scripts/validate-plan-blueprint.cjs +358 -0
- package/templates/harness/skills/st-execute-task/SKILL.md +195 -0
- package/templates/harness/skills/st-execute-task/scripts/check-task-dependencies.cjs +420 -0
- package/templates/harness/skills/st-execute-task/scripts/find-strikethroo-root.cjs +116 -0
- package/templates/harness/skills/st-execute-task/scripts/validate-plan-blueprint.cjs +358 -0
- package/templates/harness/skills/st-full-workflow/SKILL.md +413 -0
- package/templates/harness/skills/st-full-workflow/scripts/create-feature-branch.cjs +359 -0
- package/templates/harness/skills/st-full-workflow/scripts/find-strikethroo-root.cjs +116 -0
- package/templates/harness/skills/st-full-workflow/scripts/get-next-plan-id.cjs +197 -0
- package/templates/harness/skills/st-full-workflow/scripts/get-next-task-id.cjs +295 -0
- package/templates/harness/skills/st-full-workflow/scripts/validate-plan-blueprint.cjs +358 -0
- package/templates/harness/skills/st-generate-tasks/SKILL.md +244 -0
- package/templates/harness/skills/st-generate-tasks/scripts/find-strikethroo-root.cjs +116 -0
- package/templates/harness/skills/st-generate-tasks/scripts/get-next-task-id.cjs +295 -0
- package/templates/harness/skills/st-generate-tasks/scripts/validate-plan-blueprint.cjs +358 -0
- package/templates/harness/skills/st-refine-plan/SKILL.md +205 -0
- package/templates/harness/skills/st-refine-plan/scripts/find-strikethroo-root.cjs +116 -0
- package/templates/harness/skills/st-refine-plan/scripts/validate-plan-blueprint.cjs +358 -0
- package/templates/strikethroo/README.md +7 -0
- package/templates/strikethroo/config/STRIKETHROO.md +76 -0
- package/templates/strikethroo/config/hooks/POST_ERROR_DETECTION.md +46 -0
- package/templates/strikethroo/config/hooks/POST_EXECUTION.md +25 -0
- package/templates/strikethroo/config/hooks/POST_PHASE.md +24 -0
- package/templates/strikethroo/config/hooks/POST_PLAN.md +5 -0
- package/templates/strikethroo/config/hooks/POST_TASK_GENERATION_ALL.md +41 -0
- package/templates/strikethroo/config/hooks/PRE_PHASE.md +21 -0
- package/templates/strikethroo/config/hooks/PRE_PLAN.md +42 -0
- package/templates/strikethroo/config/hooks/PRE_TASK_ASSIGNMENT.md +32 -0
- package/templates/strikethroo/config/hooks/PRE_TASK_EXECUTION.md +1 -0
- package/templates/strikethroo/config/templates/BLUEPRINT_TEMPLATE.md +24 -0
- package/templates/strikethroo/config/templates/EXECUTION_SUMMARY_TEMPLATE.md +13 -0
- package/templates/strikethroo/config/templates/PLAN_TEMPLATE.md +109 -0
- package/templates/strikethroo/config/templates/TASK_TEMPLATE.md +36 -0
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Plan Utilities Module
|
|
4
|
+
*
|
|
5
|
+
* Provides functions for locating plans, loading plan data, and extracting content
|
|
6
|
+
*/
|
|
7
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
8
|
+
if (k2 === undefined) k2 = k;
|
|
9
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
10
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
11
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
12
|
+
}
|
|
13
|
+
Object.defineProperty(o, k2, desc);
|
|
14
|
+
}) : (function(o, m, k, k2) {
|
|
15
|
+
if (k2 === undefined) k2 = k;
|
|
16
|
+
o[k2] = m[k];
|
|
17
|
+
}));
|
|
18
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
19
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
20
|
+
}) : function(o, v) {
|
|
21
|
+
o["default"] = v;
|
|
22
|
+
});
|
|
23
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
24
|
+
var ownKeys = function(o) {
|
|
25
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
26
|
+
var ar = [];
|
|
27
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
28
|
+
return ar;
|
|
29
|
+
};
|
|
30
|
+
return ownKeys(o);
|
|
31
|
+
};
|
|
32
|
+
return function (mod) {
|
|
33
|
+
if (mod && mod.__esModule) return mod;
|
|
34
|
+
var result = {};
|
|
35
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
36
|
+
__setModuleDefault(result, mod);
|
|
37
|
+
return result;
|
|
38
|
+
};
|
|
39
|
+
})();
|
|
40
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
41
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
42
|
+
};
|
|
43
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
44
|
+
exports.findPlanById = findPlanById;
|
|
45
|
+
exports.extractExecutiveSummary = extractExecutiveSummary;
|
|
46
|
+
exports.loadPlanData = loadPlanData;
|
|
47
|
+
const fs = __importStar(require("fs-extra"));
|
|
48
|
+
const path = __importStar(require("path"));
|
|
49
|
+
const gray_matter_1 = __importDefault(require("gray-matter"));
|
|
50
|
+
const status_1 = require("./status");
|
|
51
|
+
/**
|
|
52
|
+
* Find a plan by ID in either plans/ or archive/ directories
|
|
53
|
+
*/
|
|
54
|
+
async function findPlanById(planId) {
|
|
55
|
+
const baseDir = process.cwd();
|
|
56
|
+
const searchDirs = [
|
|
57
|
+
{ path: path.join(baseDir, '.ai/strikethroo/plans'), archived: false },
|
|
58
|
+
{ path: path.join(baseDir, '.ai/strikethroo/archive'), archived: true },
|
|
59
|
+
];
|
|
60
|
+
for (const searchDir of searchDirs) {
|
|
61
|
+
if (!(await fs.pathExists(searchDir.path)))
|
|
62
|
+
continue;
|
|
63
|
+
const entries = await fs.readdir(searchDir.path, { withFileTypes: true });
|
|
64
|
+
for (const entry of entries) {
|
|
65
|
+
if (!entry.isDirectory())
|
|
66
|
+
continue;
|
|
67
|
+
const planDir = path.join(searchDir.path, entry.name);
|
|
68
|
+
const files = await fs.readdir(planDir);
|
|
69
|
+
const planFile = files.find(f => f.startsWith('plan-') && f.endsWith('.md'));
|
|
70
|
+
if (!planFile)
|
|
71
|
+
continue;
|
|
72
|
+
const filePath = path.join(planDir, planFile);
|
|
73
|
+
const content = await fs.readFile(filePath, 'utf-8');
|
|
74
|
+
const { data } = (0, gray_matter_1.default)(content);
|
|
75
|
+
if (data.id === planId) {
|
|
76
|
+
return {
|
|
77
|
+
planId,
|
|
78
|
+
directoryPath: planDir,
|
|
79
|
+
filePath,
|
|
80
|
+
isArchived: searchDir.archived,
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
return null;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Extract Executive Summary section from markdown content
|
|
89
|
+
*/
|
|
90
|
+
function extractExecutiveSummary(markdown) {
|
|
91
|
+
// Match from "## Executive Summary" to next ## heading or end of file
|
|
92
|
+
const regex = /## Executive Summary\n+([\s\S]*?)(?=\n## |$)/;
|
|
93
|
+
const match = markdown.match(regex);
|
|
94
|
+
if (!match || !match[1]) {
|
|
95
|
+
return 'No Executive Summary found.';
|
|
96
|
+
}
|
|
97
|
+
// Trim whitespace and return
|
|
98
|
+
return match[1].trim();
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Load complete plan data including metadata, tasks, and content
|
|
102
|
+
*/
|
|
103
|
+
async function loadPlanData(planId) {
|
|
104
|
+
const location = await findPlanById(planId);
|
|
105
|
+
if (!location)
|
|
106
|
+
return null;
|
|
107
|
+
const content = await fs.readFile(location.filePath, 'utf-8');
|
|
108
|
+
const { data, content: bodyContent } = (0, gray_matter_1.default)(content);
|
|
109
|
+
const tasks = await (0, status_1.parseTaskFiles)(location.directoryPath);
|
|
110
|
+
const executiveSummary = extractExecutiveSummary(bodyContent);
|
|
111
|
+
return {
|
|
112
|
+
id: data.id,
|
|
113
|
+
summary: data.summary,
|
|
114
|
+
created: data.created,
|
|
115
|
+
approval_method: data.approval_method,
|
|
116
|
+
isArchived: location.isArchived,
|
|
117
|
+
directoryPath: location.directoryPath,
|
|
118
|
+
tasks,
|
|
119
|
+
bodyContent,
|
|
120
|
+
executiveSummary,
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
//# sourceMappingURL=plan-utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plan-utils.js","sourceRoot":"","sources":["../src/plan-utils.ts"],"names":[],"mappings":"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"}
|
package/dist/plan.d.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plan Command Module
|
|
3
|
+
*
|
|
4
|
+
* Implements show and archive subcommands for plan inspection and management
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Display plan metadata, executive summary, and task statistics
|
|
8
|
+
*/
|
|
9
|
+
export declare function showPlan(planId: number): Promise<{
|
|
10
|
+
success: boolean;
|
|
11
|
+
message?: string;
|
|
12
|
+
}>;
|
|
13
|
+
/**
|
|
14
|
+
* Delete a plan permanently from either active or archive directory
|
|
15
|
+
*/
|
|
16
|
+
export declare function deletePlan(planId: number, autoConfirm?: boolean): Promise<{
|
|
17
|
+
success: boolean;
|
|
18
|
+
message?: string;
|
|
19
|
+
}>;
|
|
20
|
+
/**
|
|
21
|
+
* Archive a plan by moving it to the archive directory
|
|
22
|
+
*/
|
|
23
|
+
export declare function archivePlan(planId: number, autoConfirm?: boolean): Promise<{
|
|
24
|
+
success: boolean;
|
|
25
|
+
message?: string;
|
|
26
|
+
}>;
|
|
27
|
+
//# sourceMappingURL=plan.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plan.d.ts","sourceRoot":"","sources":["../src/plan.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AA0EH;;GAEG;AACH,wBAAsB,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CA8D9F;AAED;;GAEG;AACH,wBAAsB,UAAU,CAC9B,MAAM,EAAE,MAAM,EACd,WAAW,GAAE,OAAe,GAC3B,OAAO,CAAC;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAyCjD;AAED;;GAEG;AACH,wBAAsB,WAAW,CAC/B,MAAM,EAAE,MAAM,EACd,WAAW,GAAE,OAAe,GAC3B,OAAO,CAAC;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CA8FjD"}
|
package/dist/plan.js
ADDED
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Plan Command Module
|
|
4
|
+
*
|
|
5
|
+
* Implements show and archive subcommands for plan inspection and management
|
|
6
|
+
*/
|
|
7
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
8
|
+
if (k2 === undefined) k2 = k;
|
|
9
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
10
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
11
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
12
|
+
}
|
|
13
|
+
Object.defineProperty(o, k2, desc);
|
|
14
|
+
}) : (function(o, m, k, k2) {
|
|
15
|
+
if (k2 === undefined) k2 = k;
|
|
16
|
+
o[k2] = m[k];
|
|
17
|
+
}));
|
|
18
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
19
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
20
|
+
}) : function(o, v) {
|
|
21
|
+
o["default"] = v;
|
|
22
|
+
});
|
|
23
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
24
|
+
var ownKeys = function(o) {
|
|
25
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
26
|
+
var ar = [];
|
|
27
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
28
|
+
return ar;
|
|
29
|
+
};
|
|
30
|
+
return ownKeys(o);
|
|
31
|
+
};
|
|
32
|
+
return function (mod) {
|
|
33
|
+
if (mod && mod.__esModule) return mod;
|
|
34
|
+
var result = {};
|
|
35
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
36
|
+
__setModuleDefault(result, mod);
|
|
37
|
+
return result;
|
|
38
|
+
};
|
|
39
|
+
})();
|
|
40
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
41
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
42
|
+
};
|
|
43
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
44
|
+
exports.showPlan = showPlan;
|
|
45
|
+
exports.deletePlan = deletePlan;
|
|
46
|
+
exports.archivePlan = archivePlan;
|
|
47
|
+
const fs = __importStar(require("fs-extra"));
|
|
48
|
+
const path = __importStar(require("path"));
|
|
49
|
+
const gray_matter_1 = __importDefault(require("gray-matter"));
|
|
50
|
+
const readline = __importStar(require("readline"));
|
|
51
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
52
|
+
const plan_utils_1 = require("./plan-utils");
|
|
53
|
+
const TERM_WIDTH = 80;
|
|
54
|
+
const DIVIDER = '─'.repeat(TERM_WIDTH);
|
|
55
|
+
/**
|
|
56
|
+
* Format a section header
|
|
57
|
+
*/
|
|
58
|
+
function formatSectionHeader(title) {
|
|
59
|
+
return `\n${chalk_1.default.cyan.bold(title)}\n${chalk_1.default.cyan(DIVIDER)}\n`;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Create an ASCII progress bar
|
|
63
|
+
*/
|
|
64
|
+
function createProgressBar(percentage, width = 20) {
|
|
65
|
+
const filled = Math.round((percentage / 100) * width);
|
|
66
|
+
const empty = width - filled;
|
|
67
|
+
const bar = chalk_1.default.green('█'.repeat(filled)) + chalk_1.default.gray('░'.repeat(empty));
|
|
68
|
+
return `[${bar}] ${percentage}%`;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Wrap text to specified width, preserving paragraphs
|
|
72
|
+
*/
|
|
73
|
+
function wrapText(text, maxWidth) {
|
|
74
|
+
const paragraphs = text.split('\n\n');
|
|
75
|
+
return paragraphs
|
|
76
|
+
.map(paragraph => {
|
|
77
|
+
const words = paragraph.split(/\s+/);
|
|
78
|
+
const lines = [];
|
|
79
|
+
let currentLine = '';
|
|
80
|
+
for (const word of words) {
|
|
81
|
+
if (currentLine.length + word.length + 1 <= maxWidth) {
|
|
82
|
+
currentLine += (currentLine ? ' ' : '') + word;
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
if (currentLine)
|
|
86
|
+
lines.push(currentLine);
|
|
87
|
+
currentLine = word;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
if (currentLine)
|
|
91
|
+
lines.push(currentLine);
|
|
92
|
+
return lines.join('\n');
|
|
93
|
+
})
|
|
94
|
+
.join('\n\n');
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Prompt user for yes/no confirmation
|
|
98
|
+
*/
|
|
99
|
+
async function promptConfirmation(question) {
|
|
100
|
+
const rl = readline.createInterface({
|
|
101
|
+
input: process.stdin,
|
|
102
|
+
output: process.stdout,
|
|
103
|
+
});
|
|
104
|
+
return new Promise(resolve => {
|
|
105
|
+
rl.question(question, answer => {
|
|
106
|
+
rl.close();
|
|
107
|
+
resolve(answer.toLowerCase() === 'y' || answer.toLowerCase() === 'yes');
|
|
108
|
+
});
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Display plan metadata, executive summary, and task statistics
|
|
113
|
+
*/
|
|
114
|
+
async function showPlan(planId) {
|
|
115
|
+
try {
|
|
116
|
+
const planData = await (0, plan_utils_1.loadPlanData)(planId);
|
|
117
|
+
if (!planData) {
|
|
118
|
+
return {
|
|
119
|
+
success: false,
|
|
120
|
+
message: `Plan ${planId} not found. Check .ai/strikethroo/plans/ and .ai/strikethroo/archive/`,
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
// Build output
|
|
124
|
+
let output = '';
|
|
125
|
+
// Header
|
|
126
|
+
output += chalk_1.default.bold.white(`\nPlan ${planData.id}\n`);
|
|
127
|
+
output += chalk_1.default.gray(DIVIDER) + '\n';
|
|
128
|
+
// Metadata section
|
|
129
|
+
output += formatSectionHeader('Metadata');
|
|
130
|
+
output += ` ${chalk_1.default.cyan('●')} ID: ${planData.id}\n`;
|
|
131
|
+
output += ` ${chalk_1.default.cyan('●')} Created: ${planData.created}\n`;
|
|
132
|
+
output += ` ${chalk_1.default.cyan('●')} Status: ${planData.isArchived ? chalk_1.default.blue('Archived') : chalk_1.default.green('Active')}\n`;
|
|
133
|
+
output += ` ${chalk_1.default.cyan('●')} Summary: ${planData.summary}\n`;
|
|
134
|
+
output += ` ${chalk_1.default.cyan('●')} Approval: ${planData.approval_method ?? 'unset'}\n`;
|
|
135
|
+
// Task statistics section
|
|
136
|
+
const taskCount = planData.tasks.length;
|
|
137
|
+
const completedCount = planData.tasks.filter(t => t.status === 'completed').length;
|
|
138
|
+
const percentage = taskCount > 0 ? Math.round((completedCount / taskCount) * 100) : 0;
|
|
139
|
+
output += formatSectionHeader('Task Progress');
|
|
140
|
+
if (taskCount > 0) {
|
|
141
|
+
output += ` ${createProgressBar(percentage, 20)} ${completedCount}/${taskCount} tasks completed\n`;
|
|
142
|
+
}
|
|
143
|
+
else {
|
|
144
|
+
output += ` ${chalk_1.default.gray('No tasks generated yet')}\n`;
|
|
145
|
+
}
|
|
146
|
+
// Executive Summary section
|
|
147
|
+
output += formatSectionHeader('Executive Summary');
|
|
148
|
+
// Word wrap the executive summary to 76 chars (80 - 4 for indent)
|
|
149
|
+
const wrappedSummary = wrapText(planData.executiveSummary, 76);
|
|
150
|
+
output +=
|
|
151
|
+
wrappedSummary
|
|
152
|
+
.split('\n')
|
|
153
|
+
.map(line => ` ${line}`)
|
|
154
|
+
.join('\n') + '\n';
|
|
155
|
+
// Footer
|
|
156
|
+
output += '\n' + chalk_1.default.gray(DIVIDER) + '\n';
|
|
157
|
+
console.log(output);
|
|
158
|
+
return { success: true };
|
|
159
|
+
}
|
|
160
|
+
catch (error) {
|
|
161
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
162
|
+
return {
|
|
163
|
+
success: false,
|
|
164
|
+
message: `Failed to display plan: ${message}`,
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Delete a plan permanently from either active or archive directory
|
|
170
|
+
*/
|
|
171
|
+
async function deletePlan(planId, autoConfirm = false) {
|
|
172
|
+
try {
|
|
173
|
+
// 1. Find the plan
|
|
174
|
+
const location = await (0, plan_utils_1.findPlanById)(planId);
|
|
175
|
+
if (!location) {
|
|
176
|
+
return {
|
|
177
|
+
success: false,
|
|
178
|
+
message: `Plan ${planId} not found. Check .ai/strikethroo/plans/ and .ai/strikethroo/archive/ directories.`,
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
// 2. Prompt for confirmation (unless autoConfirm is true)
|
|
182
|
+
if (!autoConfirm) {
|
|
183
|
+
const planType = location.isArchived ? 'archived' : 'active';
|
|
184
|
+
console.log(chalk_1.default.yellow(`\n⚠ Warning: This will permanently delete ${planType} plan ${planId} and all its tasks.\n`));
|
|
185
|
+
const confirmed = await promptConfirmation('Delete plan? (y/n): ');
|
|
186
|
+
if (!confirmed) {
|
|
187
|
+
return { success: false, message: 'Deletion cancelled by user.' };
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
// 3. Delete the directory
|
|
191
|
+
await fs.remove(location.directoryPath);
|
|
192
|
+
// 4. Display success message
|
|
193
|
+
console.log(chalk_1.default.green(`\n✓ Plan ${planId} successfully deleted.\n`));
|
|
194
|
+
return { success: true };
|
|
195
|
+
}
|
|
196
|
+
catch (error) {
|
|
197
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
198
|
+
return {
|
|
199
|
+
success: false,
|
|
200
|
+
message: `Failed to delete plan: ${message}`,
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Archive a plan by moving it to the archive directory
|
|
206
|
+
*/
|
|
207
|
+
async function archivePlan(planId, autoConfirm = false) {
|
|
208
|
+
try {
|
|
209
|
+
// 1. Find and validate plan location
|
|
210
|
+
const location = await (0, plan_utils_1.findPlanById)(planId);
|
|
211
|
+
if (!location) {
|
|
212
|
+
return {
|
|
213
|
+
success: false,
|
|
214
|
+
message: `Plan ${planId} not found. Check .ai/strikethroo/plans/ directory.`,
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
if (location.isArchived) {
|
|
218
|
+
return {
|
|
219
|
+
success: false,
|
|
220
|
+
message: `Plan ${planId} is already archived.`,
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
// 2. Load plan data to check for incomplete tasks
|
|
224
|
+
const planData = await (0, plan_utils_1.loadPlanData)(planId);
|
|
225
|
+
if (!planData) {
|
|
226
|
+
return { success: false, message: `Failed to load plan ${planId} data.` };
|
|
227
|
+
}
|
|
228
|
+
const incompleteTasks = planData.tasks.filter(t => t.status !== 'completed');
|
|
229
|
+
// 3. Warn user if incomplete tasks exist
|
|
230
|
+
if (incompleteTasks.length > 0 && !autoConfirm) {
|
|
231
|
+
console.log(chalk_1.default.yellow(`\n⚠ Warning: Plan ${planId} has ${incompleteTasks.length} incomplete task(s).\n`));
|
|
232
|
+
const confirmed = await promptConfirmation('Archive anyway? (y/n): ');
|
|
233
|
+
if (!confirmed) {
|
|
234
|
+
return { success: false, message: 'Archive cancelled by user.' };
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
// 4. Update all task files to completed status
|
|
238
|
+
const tasksDir = path.join(location.directoryPath, 'tasks');
|
|
239
|
+
if (await fs.pathExists(tasksDir)) {
|
|
240
|
+
const taskFiles = await fs.readdir(tasksDir);
|
|
241
|
+
for (const file of taskFiles) {
|
|
242
|
+
if (!file.endsWith('.md'))
|
|
243
|
+
continue;
|
|
244
|
+
const taskPath = path.join(tasksDir, file);
|
|
245
|
+
const content = await fs.readFile(taskPath, 'utf-8');
|
|
246
|
+
const parsed = (0, gray_matter_1.default)(content);
|
|
247
|
+
// Update status to completed
|
|
248
|
+
parsed.data.status = 'completed';
|
|
249
|
+
// Write back with updated frontmatter
|
|
250
|
+
const updated = gray_matter_1.default.stringify(parsed.content, parsed.data);
|
|
251
|
+
await fs.writeFile(taskPath, updated, 'utf-8');
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
// 5. Append "Manually archived" note to plan document
|
|
255
|
+
const planContent = await fs.readFile(location.filePath, 'utf-8');
|
|
256
|
+
const today = new Date().toISOString().split('T')[0]; // YYYY-MM-DD format
|
|
257
|
+
const archiveNote = `\n---\n\n**Note**: Manually archived on ${today}\n`;
|
|
258
|
+
const updatedContent = planContent + archiveNote;
|
|
259
|
+
await fs.writeFile(location.filePath, updatedContent, 'utf-8');
|
|
260
|
+
// 6. Move plan directory to archive
|
|
261
|
+
const baseDir = process.cwd();
|
|
262
|
+
const archiveDir = path.join(baseDir, '.ai/strikethroo/archive');
|
|
263
|
+
await fs.ensureDir(archiveDir);
|
|
264
|
+
const planDirName = path.basename(location.directoryPath);
|
|
265
|
+
const archivePath = path.join(archiveDir, planDirName);
|
|
266
|
+
await fs.move(location.directoryPath, archivePath);
|
|
267
|
+
// 7. Display success message
|
|
268
|
+
console.log(chalk_1.default.green(`\n✓ Plan ${planId} successfully archived to .ai/strikethroo/archive/${planDirName}\n`));
|
|
269
|
+
return { success: true };
|
|
270
|
+
}
|
|
271
|
+
catch (error) {
|
|
272
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
273
|
+
return {
|
|
274
|
+
success: false,
|
|
275
|
+
message: `Failed to archive plan: ${message}`,
|
|
276
|
+
};
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
//# sourceMappingURL=plan.js.map
|
package/dist/plan.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plan.js","sourceRoot":"","sources":["../src/plan.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Interactive Prompts for Conflict Resolution
|
|
3
|
+
*
|
|
4
|
+
* This file handles user interaction when file conflicts are detected,
|
|
5
|
+
* displaying unified diffs and collecting resolution decisions
|
|
6
|
+
*/
|
|
7
|
+
import { FileConflict, ConflictResolution } from './types';
|
|
8
|
+
/**
|
|
9
|
+
* Prompt user for resolution of a single file conflict
|
|
10
|
+
* @param conflict - FileConflict object to resolve
|
|
11
|
+
* @param remainingCount - Number of conflicts remaining after this one
|
|
12
|
+
* @returns User's resolution choice
|
|
13
|
+
*/
|
|
14
|
+
export declare function promptForResolution(conflict: FileConflict, remainingCount: number): Promise<ConflictResolution>;
|
|
15
|
+
/**
|
|
16
|
+
* Process all file conflicts with user prompts
|
|
17
|
+
* @param conflicts - Array of FileConflict objects
|
|
18
|
+
* @returns Map of relative paths to resolution decisions
|
|
19
|
+
*/
|
|
20
|
+
export declare function promptForConflicts(conflicts: FileConflict[]): Promise<Map<string, ConflictResolution>>;
|
|
21
|
+
//# sourceMappingURL=prompts.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompts.d.ts","sourceRoot":"","sources":["../src/prompts.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AA4C3D;;;;;GAKG;AACH,wBAAsB,mBAAmB,CACvC,QAAQ,EAAE,YAAY,EACtB,cAAc,EAAE,MAAM,GACrB,OAAO,CAAC,kBAAkB,CAAC,CAqD7B;AAED;;;;GAIG;AACH,wBAAsB,kBAAkB,CACtC,SAAS,EAAE,YAAY,EAAE,GACxB,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC,CA+B1C"}
|
package/dist/prompts.js
ADDED
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Interactive Prompts for Conflict Resolution
|
|
4
|
+
*
|
|
5
|
+
* This file handles user interaction when file conflicts are detected,
|
|
6
|
+
* displaying unified diffs and collecting resolution decisions
|
|
7
|
+
*/
|
|
8
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
9
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.promptForResolution = promptForResolution;
|
|
13
|
+
exports.promptForConflicts = promptForConflicts;
|
|
14
|
+
const inquirer_1 = __importDefault(require("inquirer"));
|
|
15
|
+
const diff_1 = require("diff");
|
|
16
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
17
|
+
/**
|
|
18
|
+
* Format and colorize a unified diff for display
|
|
19
|
+
* @param diff - Unified diff string from diff library
|
|
20
|
+
* @returns Colorized diff string
|
|
21
|
+
*/
|
|
22
|
+
function formatDiff(diff) {
|
|
23
|
+
const lines = diff.split('\n');
|
|
24
|
+
return lines
|
|
25
|
+
.map(line => {
|
|
26
|
+
if (line.startsWith('+++') || line.startsWith('---')) {
|
|
27
|
+
return chalk_1.default.bold(line);
|
|
28
|
+
}
|
|
29
|
+
else if (line.startsWith('+')) {
|
|
30
|
+
return chalk_1.default.green(line);
|
|
31
|
+
}
|
|
32
|
+
else if (line.startsWith('-')) {
|
|
33
|
+
return chalk_1.default.red(line);
|
|
34
|
+
}
|
|
35
|
+
else if (line.startsWith('@@')) {
|
|
36
|
+
return chalk_1.default.cyan(line);
|
|
37
|
+
}
|
|
38
|
+
return line;
|
|
39
|
+
})
|
|
40
|
+
.join('\n');
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Generate a unified diff between user's file and new file
|
|
44
|
+
* @param conflict - FileConflict object with user and new file contents
|
|
45
|
+
* @returns Formatted unified diff string
|
|
46
|
+
*/
|
|
47
|
+
function generateDiff(conflict) {
|
|
48
|
+
const diff = (0, diff_1.createTwoFilesPatch)(`${conflict.relativePath} (your version)`, `${conflict.relativePath} (new version)`, conflict.userFileContent, conflict.newFileContent, '', '', { context: 3 });
|
|
49
|
+
return formatDiff(diff);
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Prompt user for resolution of a single file conflict
|
|
53
|
+
* @param conflict - FileConflict object to resolve
|
|
54
|
+
* @param remainingCount - Number of conflicts remaining after this one
|
|
55
|
+
* @returns User's resolution choice
|
|
56
|
+
*/
|
|
57
|
+
async function promptForResolution(conflict, remainingCount) {
|
|
58
|
+
console.log('');
|
|
59
|
+
console.log(chalk_1.default.bold.yellow('⚠️ File Conflict Detected'));
|
|
60
|
+
console.log('');
|
|
61
|
+
console.log(chalk_1.default.bold(`File: ${chalk_1.default.cyan(conflict.relativePath)} has been modified since last init.`));
|
|
62
|
+
console.log(chalk_1.default.yellow('Your changes will be lost if you choose to overwrite with the new version.'));
|
|
63
|
+
console.log('');
|
|
64
|
+
// Generate and display unified diff
|
|
65
|
+
const diff = generateDiff(conflict);
|
|
66
|
+
console.log(diff);
|
|
67
|
+
console.log('');
|
|
68
|
+
// Build choices based on remaining conflicts
|
|
69
|
+
const choices = [
|
|
70
|
+
{
|
|
71
|
+
name: 'Keep my changes (skip update)',
|
|
72
|
+
value: 'keep',
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
name: 'Overwrite with new version',
|
|
76
|
+
value: 'overwrite',
|
|
77
|
+
},
|
|
78
|
+
];
|
|
79
|
+
// Add batch options if there are more conflicts
|
|
80
|
+
if (remainingCount > 0) {
|
|
81
|
+
choices.push({
|
|
82
|
+
name: `Keep my changes for all remaining conflicts (${remainingCount + 1} files)`,
|
|
83
|
+
value: 'keep-all',
|
|
84
|
+
}, {
|
|
85
|
+
name: `Overwrite all remaining conflicts (${remainingCount + 1} files)`,
|
|
86
|
+
value: 'overwrite-all',
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
const answer = await inquirer_1.default.prompt([
|
|
90
|
+
{
|
|
91
|
+
type: 'list',
|
|
92
|
+
name: 'resolution',
|
|
93
|
+
message: 'What would you like to do?',
|
|
94
|
+
choices,
|
|
95
|
+
},
|
|
96
|
+
]);
|
|
97
|
+
return answer.resolution;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Process all file conflicts with user prompts
|
|
101
|
+
* @param conflicts - Array of FileConflict objects
|
|
102
|
+
* @returns Map of relative paths to resolution decisions
|
|
103
|
+
*/
|
|
104
|
+
async function promptForConflicts(conflicts) {
|
|
105
|
+
const resolutions = new Map();
|
|
106
|
+
let batchResolution = null;
|
|
107
|
+
for (let i = 0; i < conflicts.length; i++) {
|
|
108
|
+
const conflict = conflicts[i];
|
|
109
|
+
if (!conflict)
|
|
110
|
+
continue; // TypeScript safety check
|
|
111
|
+
const remainingCount = conflicts.length - i - 1;
|
|
112
|
+
// If batch resolution was set, apply it
|
|
113
|
+
if (batchResolution) {
|
|
114
|
+
const resolution = batchResolution === 'keep-all' ? 'keep' : 'overwrite';
|
|
115
|
+
resolutions.set(conflict.relativePath, resolution);
|
|
116
|
+
continue;
|
|
117
|
+
}
|
|
118
|
+
// Prompt user for this conflict
|
|
119
|
+
const resolution = await promptForResolution(conflict, remainingCount);
|
|
120
|
+
// Handle batch resolutions
|
|
121
|
+
if (resolution === 'keep-all' || resolution === 'overwrite-all') {
|
|
122
|
+
batchResolution = resolution;
|
|
123
|
+
const individualResolution = resolution === 'keep-all' ? 'keep' : 'overwrite';
|
|
124
|
+
resolutions.set(conflict.relativePath, individualResolution);
|
|
125
|
+
}
|
|
126
|
+
else {
|
|
127
|
+
resolutions.set(conflict.relativePath, resolution);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
return resolutions;
|
|
131
|
+
}
|
|
132
|
+
//# sourceMappingURL=prompts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompts.js","sourceRoot":"","sources":["../src/prompts.ts"],"names":[],"mappings":"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"}
|