@bicorne/task-flow 0.1.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 +252 -0
- package/SKILL.md +250 -0
- package/assets/.harnessrc +10 -0
- package/assets/PHASE-task.json.example +50 -0
- package/assets/design.md +69 -0
- package/assets/hooks.json +15 -0
- package/assets/product-requirement.md +82 -0
- package/assets/schema.json +127 -0
- package/assets/tasks.md +26 -0
- package/dist/commands/analyze.d.ts +32 -0
- package/dist/commands/analyze.js +338 -0
- package/dist/commands/archive.d.ts +11 -0
- package/dist/commands/archive.js +53 -0
- package/dist/commands/design.d.ts +38 -0
- package/dist/commands/design.js +492 -0
- package/dist/commands/extract.d.ts +31 -0
- package/dist/commands/extract.js +477 -0
- package/dist/commands/init.d.ts +24 -0
- package/dist/commands/init.js +165 -0
- package/dist/commands/merge/index.d.ts +17 -0
- package/dist/commands/merge/index.js +322 -0
- package/dist/commands/merge/merger.d.ts +18 -0
- package/dist/commands/merge/merger.js +151 -0
- package/dist/commands/merge/types.d.ts +67 -0
- package/dist/commands/merge/types.js +6 -0
- package/dist/commands/merge/validators.d.ts +14 -0
- package/dist/commands/merge/validators.js +147 -0
- package/dist/commands/merge.d.ts +7 -0
- package/dist/commands/merge.js +15 -0
- package/dist/commands/start.d.ts +32 -0
- package/dist/commands/start.js +265 -0
- package/dist/commands/status.d.ts +15 -0
- package/dist/commands/status.js +143 -0
- package/dist/commands/sync.d.ts +11 -0
- package/dist/commands/sync.js +58 -0
- package/dist/commands/tasks-gen/doc-parser.d.ts +7 -0
- package/dist/commands/tasks-gen/doc-parser.js +259 -0
- package/dist/commands/tasks-gen/generators.d.ts +33 -0
- package/dist/commands/tasks-gen/generators.js +141 -0
- package/dist/commands/tasks-gen/index.d.ts +30 -0
- package/dist/commands/tasks-gen/index.js +345 -0
- package/dist/commands/tasks-gen/parsers.d.ts +29 -0
- package/dist/commands/tasks-gen/parsers.js +272 -0
- package/dist/commands/tasks-gen/templates.d.ts +8 -0
- package/dist/commands/tasks-gen/templates.js +37 -0
- package/dist/commands/tasks-gen/types.d.ts +71 -0
- package/dist/commands/tasks-gen/types.js +17 -0
- package/dist/commands/tasks-gen/validators.d.ts +14 -0
- package/dist/commands/tasks-gen/validators.js +54 -0
- package/dist/commands/tasks.d.ts +9 -0
- package/dist/commands/tasks.js +22 -0
- package/dist/commands/worktree.d.ts +28 -0
- package/dist/commands/worktree.js +275 -0
- package/dist/hooks/check-prd-exists.d.ts +20 -0
- package/dist/hooks/check-prd-exists.js +61 -0
- package/dist/hooks/check-worktree-conflict.d.ts +34 -0
- package/dist/hooks/check-worktree-conflict.js +107 -0
- package/dist/hooks/hook-runner/executor.d.ts +18 -0
- package/dist/hooks/hook-runner/executor.js +143 -0
- package/dist/hooks/hook-runner/index.d.ts +64 -0
- package/dist/hooks/hook-runner/index.js +220 -0
- package/dist/hooks/hook-runner/loader.d.ts +23 -0
- package/dist/hooks/hook-runner/loader.js +126 -0
- package/dist/hooks/hook-runner/types.d.ts +59 -0
- package/dist/hooks/hook-runner/types.js +6 -0
- package/dist/hooks/hook-runner.d.ts +9 -0
- package/dist/hooks/hook-runner.js +30 -0
- package/dist/hooks/phase-complete-detector.d.ts +35 -0
- package/dist/hooks/phase-complete-detector.js +203 -0
- package/dist/hooks/phase-gate-validator.d.ts +76 -0
- package/dist/hooks/phase-gate-validator.js +407 -0
- package/dist/hooks/save-checkpoint.d.ts +43 -0
- package/dist/hooks/save-checkpoint.js +144 -0
- package/dist/hooks/start-mcp-servers.d.ts +50 -0
- package/dist/hooks/start-mcp-servers.js +75 -0
- package/dist/hooks/stop-mcp-servers.d.ts +40 -0
- package/dist/hooks/stop-mcp-servers.js +58 -0
- package/dist/index.d.ts +29 -0
- package/dist/index.js +238 -0
- package/dist/lib/archive.d.ts +31 -0
- package/dist/lib/archive.js +226 -0
- package/dist/lib/config.d.ts +93 -0
- package/dist/lib/config.js +251 -0
- package/dist/lib/constants.d.ts +222 -0
- package/dist/lib/constants.js +247 -0
- package/dist/lib/interactive.d.ts +31 -0
- package/dist/lib/interactive.js +166 -0
- package/dist/lib/mcp-client.d.ts +156 -0
- package/dist/lib/mcp-client.js +370 -0
- package/dist/lib/state.d.ts +119 -0
- package/dist/lib/state.js +293 -0
- package/dist/slash/executor.d.ts +22 -0
- package/dist/slash/executor.js +259 -0
- package/dist/slash/index.d.ts +11 -0
- package/dist/slash/index.js +45 -0
- package/dist/slash/parser.d.ts +24 -0
- package/dist/slash/parser.js +101 -0
- package/dist/slash/registry.d.ts +22 -0
- package/dist/slash/registry.js +155 -0
- package/dist/spec/openspec-to-task/builders.d.ts +107 -0
- package/dist/spec/openspec-to-task/builders.js +138 -0
- package/dist/spec/openspec-to-task/index.d.ts +20 -0
- package/dist/spec/openspec-to-task/index.js +182 -0
- package/dist/spec/openspec-to-task/parsers.d.ts +65 -0
- package/dist/spec/openspec-to-task/parsers.js +232 -0
- package/dist/spec/openspec-to-task/types.d.ts +49 -0
- package/dist/spec/openspec-to-task/types.js +6 -0
- package/dist/spec/sync-openspec-to-task.d.ts +7 -0
- package/dist/spec/sync-openspec-to-task.js +21 -0
- package/dist/spec/sync-task-to-openspec.d.ts +27 -0
- package/dist/spec/sync-task-to-openspec.js +288 -0
- package/dist/types/ai-context.d.ts +108 -0
- package/dist/types/ai-context.js +9 -0
- package/package.json +66 -0
- package/references/AI-CONVERSATION-TUTORIAL.md +270 -0
- package/references/CLI-TUTORIAL.md +447 -0
- package/references/GIT-WORKTREE-SOP.md +109 -0
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* commands/tasks-gen/types.ts
|
|
3
|
+
* Type definitions for task generation
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Task definition interface
|
|
7
|
+
*/
|
|
8
|
+
export interface Task {
|
|
9
|
+
id: string;
|
|
10
|
+
type: 'feat' | 'fix' | 'refactor' | 'test' | 'docs';
|
|
11
|
+
title: string;
|
|
12
|
+
priority: 'high' | 'medium' | 'low';
|
|
13
|
+
phase: number;
|
|
14
|
+
subphase?: number;
|
|
15
|
+
sequence?: number;
|
|
16
|
+
dependencies?: string[];
|
|
17
|
+
docs_to_read?: string[];
|
|
18
|
+
spec: {
|
|
19
|
+
description: string;
|
|
20
|
+
files: string[];
|
|
21
|
+
context?: string[];
|
|
22
|
+
};
|
|
23
|
+
acceptance_criteria?: string[];
|
|
24
|
+
implementation?: {
|
|
25
|
+
steps?: Array<{
|
|
26
|
+
step: string;
|
|
27
|
+
details?: string;
|
|
28
|
+
}>;
|
|
29
|
+
notes?: string;
|
|
30
|
+
};
|
|
31
|
+
validation?: {
|
|
32
|
+
commands?: string[];
|
|
33
|
+
manual_checks?: string[];
|
|
34
|
+
};
|
|
35
|
+
status: 'pending' | 'in_progress' | 'completed' | 'blocked';
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Tasks generation options
|
|
39
|
+
*/
|
|
40
|
+
export interface TasksGenOptions {
|
|
41
|
+
cwd?: string;
|
|
42
|
+
change?: string;
|
|
43
|
+
type?: string;
|
|
44
|
+
priority?: string;
|
|
45
|
+
yes?: boolean;
|
|
46
|
+
input?: string;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Tasks generation result
|
|
50
|
+
*/
|
|
51
|
+
export interface TasksGenResult {
|
|
52
|
+
success: boolean;
|
|
53
|
+
reason?: string;
|
|
54
|
+
message?: string;
|
|
55
|
+
changeName?: string;
|
|
56
|
+
tasksPath?: string;
|
|
57
|
+
tasksDir?: string;
|
|
58
|
+
manifestPath?: string;
|
|
59
|
+
generatedFiles?: string[];
|
|
60
|
+
totalTasks?: number;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Task schema constants
|
|
64
|
+
*/
|
|
65
|
+
export declare const TASK_SCHEMA: {
|
|
66
|
+
required: string[];
|
|
67
|
+
idPattern: RegExp;
|
|
68
|
+
types: string[];
|
|
69
|
+
priorities: string[];
|
|
70
|
+
statuses: string[];
|
|
71
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* commands/tasks-gen/types.ts
|
|
4
|
+
* Type definitions for task generation
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.TASK_SCHEMA = void 0;
|
|
8
|
+
/**
|
|
9
|
+
* Task schema constants
|
|
10
|
+
*/
|
|
11
|
+
exports.TASK_SCHEMA = {
|
|
12
|
+
required: ['id', 'type', 'title', 'priority', 'phase', 'status', 'spec'],
|
|
13
|
+
idPattern: /^PHASE-[0-9]+-[0-9]+-[0-9]+$/,
|
|
14
|
+
types: ['feat', 'fix', 'refactor', 'test', 'docs'],
|
|
15
|
+
priorities: ['high', 'medium', 'low'],
|
|
16
|
+
statuses: ['pending', 'in_progress', 'completed', 'blocked'],
|
|
17
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* commands/tasks-gen/validators.ts
|
|
3
|
+
* Validation utilities for task generation
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Validate required files exist
|
|
7
|
+
*/
|
|
8
|
+
export declare function validateRequiredFiles(paths: {
|
|
9
|
+
productRequirement: string;
|
|
10
|
+
}): {
|
|
11
|
+
valid: boolean;
|
|
12
|
+
reason?: string;
|
|
13
|
+
message?: string;
|
|
14
|
+
};
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* commands/tasks-gen/validators.ts
|
|
4
|
+
* Validation utilities for task generation
|
|
5
|
+
*/
|
|
6
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
7
|
+
if (k2 === undefined) k2 = k;
|
|
8
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
9
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
10
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
11
|
+
}
|
|
12
|
+
Object.defineProperty(o, k2, desc);
|
|
13
|
+
}) : (function(o, m, k, k2) {
|
|
14
|
+
if (k2 === undefined) k2 = k;
|
|
15
|
+
o[k2] = m[k];
|
|
16
|
+
}));
|
|
17
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
18
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
19
|
+
}) : function(o, v) {
|
|
20
|
+
o["default"] = v;
|
|
21
|
+
});
|
|
22
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
23
|
+
var ownKeys = function(o) {
|
|
24
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
25
|
+
var ar = [];
|
|
26
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
27
|
+
return ar;
|
|
28
|
+
};
|
|
29
|
+
return ownKeys(o);
|
|
30
|
+
};
|
|
31
|
+
return function (mod) {
|
|
32
|
+
if (mod && mod.__esModule) return mod;
|
|
33
|
+
var result = {};
|
|
34
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
35
|
+
__setModuleDefault(result, mod);
|
|
36
|
+
return result;
|
|
37
|
+
};
|
|
38
|
+
})();
|
|
39
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
40
|
+
exports.validateRequiredFiles = validateRequiredFiles;
|
|
41
|
+
const fs = __importStar(require("fs"));
|
|
42
|
+
/**
|
|
43
|
+
* Validate required files exist
|
|
44
|
+
*/
|
|
45
|
+
function validateRequiredFiles(paths) {
|
|
46
|
+
if (!fs.existsSync(paths.productRequirement)) {
|
|
47
|
+
return {
|
|
48
|
+
valid: false,
|
|
49
|
+
reason: 'product-requirement-not-found',
|
|
50
|
+
message: `product-requirement.md not found: ${paths.productRequirement}`,
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
return { valid: true };
|
|
54
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* commands/tasks-gen.ts
|
|
3
|
+
* Backward-compatible re-export from tasks-gen/ module
|
|
4
|
+
* @deprecated Import from './tasks-gen/index' directly
|
|
5
|
+
*/
|
|
6
|
+
export { generateTasks, main, default } from './tasks-gen/index';
|
|
7
|
+
export { Task, TasksGenOptions, TasksGenResult, TASK_SCHEMA } from './tasks-gen/types';
|
|
8
|
+
export { parseTasksMd } from './tasks-gen/parsers';
|
|
9
|
+
export { generatePhaseJson, generateManifestJson } from './tasks-gen/generators';
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* commands/tasks-gen.ts
|
|
4
|
+
* Backward-compatible re-export from tasks-gen/ module
|
|
5
|
+
* @deprecated Import from './tasks-gen/index' directly
|
|
6
|
+
*/
|
|
7
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
8
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
9
|
+
};
|
|
10
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
+
exports.generateManifestJson = exports.generatePhaseJson = exports.parseTasksMd = exports.TASK_SCHEMA = exports.default = exports.main = exports.generateTasks = void 0;
|
|
12
|
+
var index_1 = require("./tasks-gen/index");
|
|
13
|
+
Object.defineProperty(exports, "generateTasks", { enumerable: true, get: function () { return index_1.generateTasks; } });
|
|
14
|
+
Object.defineProperty(exports, "main", { enumerable: true, get: function () { return index_1.main; } });
|
|
15
|
+
Object.defineProperty(exports, "default", { enumerable: true, get: function () { return __importDefault(index_1).default; } });
|
|
16
|
+
var types_1 = require("./tasks-gen/types");
|
|
17
|
+
Object.defineProperty(exports, "TASK_SCHEMA", { enumerable: true, get: function () { return types_1.TASK_SCHEMA; } });
|
|
18
|
+
var parsers_1 = require("./tasks-gen/parsers");
|
|
19
|
+
Object.defineProperty(exports, "parseTasksMd", { enumerable: true, get: function () { return parsers_1.parseTasksMd; } });
|
|
20
|
+
var generators_1 = require("./tasks-gen/generators");
|
|
21
|
+
Object.defineProperty(exports, "generatePhaseJson", { enumerable: true, get: function () { return generators_1.generatePhaseJson; } });
|
|
22
|
+
Object.defineProperty(exports, "generateManifestJson", { enumerable: true, get: function () { return generators_1.generateManifestJson; } });
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* commands/worktree.ts
|
|
3
|
+
* Create isolated git worktree for task execution
|
|
4
|
+
*/
|
|
5
|
+
export interface WorktreeOptions {
|
|
6
|
+
cwd?: string;
|
|
7
|
+
change?: string;
|
|
8
|
+
force?: boolean;
|
|
9
|
+
yes?: boolean;
|
|
10
|
+
}
|
|
11
|
+
export interface WorktreeResult {
|
|
12
|
+
success: boolean;
|
|
13
|
+
reason?: string;
|
|
14
|
+
message?: string;
|
|
15
|
+
changeName?: string;
|
|
16
|
+
taskId?: string;
|
|
17
|
+
worktreeName?: string;
|
|
18
|
+
worktreePath?: string;
|
|
19
|
+
branchName?: string;
|
|
20
|
+
harnessLink?: string;
|
|
21
|
+
}
|
|
22
|
+
export declare function createWorktree(options?: WorktreeOptions): Promise<WorktreeResult>;
|
|
23
|
+
export declare function main(): void;
|
|
24
|
+
declare const _default: {
|
|
25
|
+
createWorktree: typeof createWorktree;
|
|
26
|
+
main: typeof main;
|
|
27
|
+
};
|
|
28
|
+
export default _default;
|
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* commands/worktree.ts
|
|
4
|
+
* Create isolated git worktree for task execution
|
|
5
|
+
*/
|
|
6
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
7
|
+
if (k2 === undefined) k2 = k;
|
|
8
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
9
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
10
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
11
|
+
}
|
|
12
|
+
Object.defineProperty(o, k2, desc);
|
|
13
|
+
}) : (function(o, m, k, k2) {
|
|
14
|
+
if (k2 === undefined) k2 = k;
|
|
15
|
+
o[k2] = m[k];
|
|
16
|
+
}));
|
|
17
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
18
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
19
|
+
}) : function(o, v) {
|
|
20
|
+
o["default"] = v;
|
|
21
|
+
});
|
|
22
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
23
|
+
var ownKeys = function(o) {
|
|
24
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
25
|
+
var ar = [];
|
|
26
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
27
|
+
return ar;
|
|
28
|
+
};
|
|
29
|
+
return ownKeys(o);
|
|
30
|
+
};
|
|
31
|
+
return function (mod) {
|
|
32
|
+
if (mod && mod.__esModule) return mod;
|
|
33
|
+
var result = {};
|
|
34
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
35
|
+
__setModuleDefault(result, mod);
|
|
36
|
+
return result;
|
|
37
|
+
};
|
|
38
|
+
})();
|
|
39
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
40
|
+
exports.createWorktree = createWorktree;
|
|
41
|
+
exports.main = main;
|
|
42
|
+
const fs = __importStar(require("fs"));
|
|
43
|
+
const path = __importStar(require("path"));
|
|
44
|
+
const child_process_1 = require("child_process");
|
|
45
|
+
const config_1 = require("../lib/config");
|
|
46
|
+
const interactive_1 = require("../lib/interactive");
|
|
47
|
+
function parseArgs(argv) {
|
|
48
|
+
const args = {};
|
|
49
|
+
for (let i = 2; i < argv.length; i += 1) {
|
|
50
|
+
const token = argv[i] || '';
|
|
51
|
+
if (!token.startsWith('--')) {
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
const key = token.slice(2);
|
|
55
|
+
const next = argv[i + 1] || '';
|
|
56
|
+
if (!next || next.startsWith('--')) {
|
|
57
|
+
args[key] = true;
|
|
58
|
+
continue;
|
|
59
|
+
}
|
|
60
|
+
args[key] = next;
|
|
61
|
+
i += 1;
|
|
62
|
+
}
|
|
63
|
+
return args;
|
|
64
|
+
}
|
|
65
|
+
function toChangeName(input) {
|
|
66
|
+
return String(input || '')
|
|
67
|
+
.trim()
|
|
68
|
+
.replace(/[^a-zA-Z0-9-_]/g, '-')
|
|
69
|
+
.replace(/-+/g, '-')
|
|
70
|
+
.replace(/^-|-$/g, '');
|
|
71
|
+
}
|
|
72
|
+
function getGitBranch(cwd) {
|
|
73
|
+
try {
|
|
74
|
+
return (0, child_process_1.execSync)('git rev-parse --abbrev-ref HEAD', { cwd, encoding: 'utf8' }).trim();
|
|
75
|
+
}
|
|
76
|
+
catch {
|
|
77
|
+
return 'main';
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Validate config has required properties for worktree creation
|
|
82
|
+
*/
|
|
83
|
+
function validateConfigForWorktree(config) {
|
|
84
|
+
if (!config.projectRoot) {
|
|
85
|
+
return {
|
|
86
|
+
valid: false,
|
|
87
|
+
reason: 'missing-project-root',
|
|
88
|
+
message: 'Config missing projectRoot',
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
if (!config.worktreesDirAbs) {
|
|
92
|
+
return {
|
|
93
|
+
valid: false,
|
|
94
|
+
reason: 'missing-worktrees-dir',
|
|
95
|
+
message: 'Config missing worktreesDirAbs',
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
return { valid: true };
|
|
99
|
+
}
|
|
100
|
+
async function createWorktree(options = {}) {
|
|
101
|
+
const config = (0, config_1.loadConfig)({ cwd: options.cwd });
|
|
102
|
+
const changeName = toChangeName(options.change);
|
|
103
|
+
if (!changeName) {
|
|
104
|
+
return {
|
|
105
|
+
success: false,
|
|
106
|
+
reason: 'missing-change',
|
|
107
|
+
message: 'Missing required argument: --change <change-name>',
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
// Validate config before use
|
|
111
|
+
const configValidation = validateConfigForWorktree(config);
|
|
112
|
+
if (!configValidation.valid) {
|
|
113
|
+
return {
|
|
114
|
+
success: false,
|
|
115
|
+
reason: configValidation.reason,
|
|
116
|
+
message: configValidation.message || 'Unknown config validation error',
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
const projectRoot = config.projectRoot || process.cwd();
|
|
120
|
+
const specRoot = config.specRootAbs || path.resolve(projectRoot, 'spec');
|
|
121
|
+
const changeDir = path.resolve(specRoot, 'changes', changeName);
|
|
122
|
+
const manifestPath = path.resolve(changeDir, 'manifest.json');
|
|
123
|
+
if (!fs.existsSync(manifestPath)) {
|
|
124
|
+
return {
|
|
125
|
+
success: false,
|
|
126
|
+
reason: 'manifest-not-found',
|
|
127
|
+
message: `manifest.json not found. Run 'task-flow tasks --change ${changeName}' first.`,
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
let manifestConfig;
|
|
131
|
+
try {
|
|
132
|
+
manifestConfig = JSON.parse(fs.readFileSync(manifestPath, 'utf8'));
|
|
133
|
+
}
|
|
134
|
+
catch (error) {
|
|
135
|
+
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
|
136
|
+
return {
|
|
137
|
+
success: false,
|
|
138
|
+
reason: 'invalid-manifest',
|
|
139
|
+
message: `Failed to parse manifest.json: ${errorMessage}`,
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
const taskId = manifestConfig.taskId || changeName;
|
|
143
|
+
const taskType = manifestConfig.type || 'feat';
|
|
144
|
+
const worktreeName = `harness-${taskType}-${taskId}`;
|
|
145
|
+
const branchName = `${taskType}/${taskId}`;
|
|
146
|
+
const worktreesDir = config.worktreesDirAbs || path.resolve(projectRoot, '.worktrees');
|
|
147
|
+
const worktreePath = path.resolve(worktreesDir, worktreeName);
|
|
148
|
+
if (fs.existsSync(worktreePath)) {
|
|
149
|
+
return {
|
|
150
|
+
success: false,
|
|
151
|
+
reason: 'worktree-exists',
|
|
152
|
+
message: `Worktree already exists: ${worktreePath}. Use --force to recreate.`,
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
// Interactive confirmation
|
|
156
|
+
if (!options.yes) {
|
|
157
|
+
(0, interactive_1.printPreview)('Worktree Configuration', {
|
|
158
|
+
'Change Name': changeName,
|
|
159
|
+
'Task ID': taskId,
|
|
160
|
+
'Branch': branchName,
|
|
161
|
+
'Worktree Path': worktreePath,
|
|
162
|
+
});
|
|
163
|
+
const confirmed = await (0, interactive_1.confirm)({
|
|
164
|
+
message: 'Create worktree with above configuration?',
|
|
165
|
+
defaultYes: true,
|
|
166
|
+
});
|
|
167
|
+
if (!confirmed) {
|
|
168
|
+
return {
|
|
169
|
+
success: false,
|
|
170
|
+
reason: 'user-cancelled',
|
|
171
|
+
message: 'User cancelled the operation.',
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
try {
|
|
176
|
+
fs.mkdirSync(worktreesDir, { recursive: true });
|
|
177
|
+
const mainBranch = getGitBranch(projectRoot);
|
|
178
|
+
try {
|
|
179
|
+
(0, child_process_1.execSync)(`git worktree add "${worktreePath}" -b ${branchName} ${mainBranch}`, {
|
|
180
|
+
cwd: projectRoot,
|
|
181
|
+
stdio: 'pipe',
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
catch (error) {
|
|
185
|
+
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
|
186
|
+
if (errorMessage.includes('already exists')) {
|
|
187
|
+
(0, child_process_1.execSync)(`git worktree add "${worktreePath}" ${branchName}`, {
|
|
188
|
+
cwd: projectRoot,
|
|
189
|
+
stdio: 'pipe',
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
else {
|
|
193
|
+
throw error;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
const mainRepoRoot = projectRoot;
|
|
197
|
+
const harnessInWorktree = path.resolve(worktreePath, '.harness');
|
|
198
|
+
if (fs.existsSync(harnessInWorktree)) {
|
|
199
|
+
try {
|
|
200
|
+
fs.rmSync(harnessInWorktree, { recursive: true, force: true });
|
|
201
|
+
}
|
|
202
|
+
catch {
|
|
203
|
+
// ignore
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
try {
|
|
207
|
+
fs.symlinkSync(path.resolve(mainRepoRoot, '.harness'), harnessInWorktree, 'dir');
|
|
208
|
+
}
|
|
209
|
+
catch (symlinkError) {
|
|
210
|
+
const errorMessage = symlinkError instanceof Error ? symlinkError.message : 'Unknown error';
|
|
211
|
+
console.warn('[WORKTREE] Failed to create symlink for .harness:', errorMessage);
|
|
212
|
+
fs.mkdirSync(harnessInWorktree, { recursive: true });
|
|
213
|
+
}
|
|
214
|
+
const gitignorePath = path.resolve(worktreePath, '.gitignore');
|
|
215
|
+
let gitignoreContent = '';
|
|
216
|
+
if (fs.existsSync(gitignorePath)) {
|
|
217
|
+
gitignoreContent = fs.readFileSync(gitignorePath, 'utf8');
|
|
218
|
+
}
|
|
219
|
+
if (!gitignoreContent.includes('.harness/')) {
|
|
220
|
+
const newContent = gitignoreContent.trim() + '\n\n# Harness\n.harness/\n';
|
|
221
|
+
fs.writeFileSync(gitignorePath, newContent, 'utf8');
|
|
222
|
+
}
|
|
223
|
+
return {
|
|
224
|
+
success: true,
|
|
225
|
+
changeName,
|
|
226
|
+
taskId,
|
|
227
|
+
worktreeName,
|
|
228
|
+
worktreePath,
|
|
229
|
+
branchName,
|
|
230
|
+
harnessLink: harnessInWorktree,
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
catch (error) {
|
|
234
|
+
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
|
235
|
+
return {
|
|
236
|
+
success: false,
|
|
237
|
+
reason: 'git-error',
|
|
238
|
+
message: `Failed to create worktree: ${errorMessage}`,
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
function main() {
|
|
243
|
+
const args = parseArgs(process.argv);
|
|
244
|
+
createWorktree({
|
|
245
|
+
cwd: args.cwd,
|
|
246
|
+
change: args.change,
|
|
247
|
+
force: args.force === true,
|
|
248
|
+
yes: args.yes === true,
|
|
249
|
+
}).then((result) => {
|
|
250
|
+
if (!result.success) {
|
|
251
|
+
console.error(`[WORKTREE] ${result.message}`);
|
|
252
|
+
process.exit(1);
|
|
253
|
+
}
|
|
254
|
+
console.log('');
|
|
255
|
+
console.log('[WORKTREE] Worktree created successfully!');
|
|
256
|
+
console.log(` Change Name: ${result.changeName}`);
|
|
257
|
+
console.log(` Task ID: ${result.taskId}`);
|
|
258
|
+
console.log(` Worktree: ${result.worktreePath}`);
|
|
259
|
+
console.log(` Branch: ${result.branchName}`);
|
|
260
|
+
console.log(` Harness Link: ${result.harnessLink}`);
|
|
261
|
+
console.log('');
|
|
262
|
+
console.log('Next steps:');
|
|
263
|
+
console.log(` cd ${result.worktreePath}`);
|
|
264
|
+
console.log(' # Start implementing tasks');
|
|
265
|
+
console.log('');
|
|
266
|
+
process.exit(0);
|
|
267
|
+
});
|
|
268
|
+
}
|
|
269
|
+
if (require.main === module) {
|
|
270
|
+
main();
|
|
271
|
+
}
|
|
272
|
+
exports.default = {
|
|
273
|
+
createWorktree,
|
|
274
|
+
main,
|
|
275
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* hooks/check-prd-exists.ts
|
|
3
|
+
* Hook to check if product-requirement.md exists before generating design.md
|
|
4
|
+
*/
|
|
5
|
+
export interface CheckPrdExistsResult {
|
|
6
|
+
check: 'prd-exists';
|
|
7
|
+
exists: boolean;
|
|
8
|
+
path?: string;
|
|
9
|
+
reason?: string;
|
|
10
|
+
}
|
|
11
|
+
export interface CheckPrdExistsContext {
|
|
12
|
+
prdPath?: string;
|
|
13
|
+
[key: string]: unknown;
|
|
14
|
+
}
|
|
15
|
+
export declare function run(context: CheckPrdExistsContext): CheckPrdExistsResult;
|
|
16
|
+
declare const _default: {
|
|
17
|
+
run: typeof run;
|
|
18
|
+
name: string;
|
|
19
|
+
};
|
|
20
|
+
export default _default;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* hooks/check-prd-exists.ts
|
|
4
|
+
* Hook to check if product-requirement.md exists before generating design.md
|
|
5
|
+
*/
|
|
6
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
7
|
+
if (k2 === undefined) k2 = k;
|
|
8
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
9
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
10
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
11
|
+
}
|
|
12
|
+
Object.defineProperty(o, k2, desc);
|
|
13
|
+
}) : (function(o, m, k, k2) {
|
|
14
|
+
if (k2 === undefined) k2 = k;
|
|
15
|
+
o[k2] = m[k];
|
|
16
|
+
}));
|
|
17
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
18
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
19
|
+
}) : function(o, v) {
|
|
20
|
+
o["default"] = v;
|
|
21
|
+
});
|
|
22
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
23
|
+
var ownKeys = function(o) {
|
|
24
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
25
|
+
var ar = [];
|
|
26
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
27
|
+
return ar;
|
|
28
|
+
};
|
|
29
|
+
return ownKeys(o);
|
|
30
|
+
};
|
|
31
|
+
return function (mod) {
|
|
32
|
+
if (mod && mod.__esModule) return mod;
|
|
33
|
+
var result = {};
|
|
34
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
35
|
+
__setModuleDefault(result, mod);
|
|
36
|
+
return result;
|
|
37
|
+
};
|
|
38
|
+
})();
|
|
39
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
40
|
+
exports.run = run;
|
|
41
|
+
const fs = __importStar(require("fs"));
|
|
42
|
+
function run(context) {
|
|
43
|
+
const { prdPath } = context;
|
|
44
|
+
if (!prdPath) {
|
|
45
|
+
return {
|
|
46
|
+
check: 'prd-exists',
|
|
47
|
+
exists: false,
|
|
48
|
+
reason: 'missing-prd-path',
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
const exists = fs.existsSync(prdPath);
|
|
52
|
+
return {
|
|
53
|
+
check: 'prd-exists',
|
|
54
|
+
exists,
|
|
55
|
+
path: prdPath,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
exports.default = {
|
|
59
|
+
run,
|
|
60
|
+
name: 'check-prd-exists',
|
|
61
|
+
};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* hooks/check-worktree-conflict.ts
|
|
3
|
+
* Check for worktree conflicts to prevent multi-agent file conflicts
|
|
4
|
+
*/
|
|
5
|
+
import { Config } from '../lib/config';
|
|
6
|
+
export interface HookInput {
|
|
7
|
+
tool_input?: {
|
|
8
|
+
file_path?: string;
|
|
9
|
+
path?: string;
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
export interface ConflictResult {
|
|
13
|
+
conflict: boolean;
|
|
14
|
+
reason?: string;
|
|
15
|
+
file?: string;
|
|
16
|
+
conflictingWorktree?: string;
|
|
17
|
+
message?: string;
|
|
18
|
+
}
|
|
19
|
+
export interface CheckOptions {
|
|
20
|
+
input: HookInput;
|
|
21
|
+
config: Config;
|
|
22
|
+
state?: unknown;
|
|
23
|
+
}
|
|
24
|
+
export declare function normalizePath(inputPath: string | undefined, projectRoot: string): string;
|
|
25
|
+
/**
|
|
26
|
+
* Check for worktree conflicts
|
|
27
|
+
* @param options - Options
|
|
28
|
+
* @returns Result
|
|
29
|
+
*/
|
|
30
|
+
export declare function checkWorktreeConflict(options: CheckOptions): ConflictResult;
|
|
31
|
+
declare const _default: {
|
|
32
|
+
checkWorktreeConflict: typeof checkWorktreeConflict;
|
|
33
|
+
};
|
|
34
|
+
export default _default;
|