takt 0.1.7 → 0.2.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/README.md +136 -40
- package/dist/cli.js +11 -2
- package/dist/cli.js.map +1 -1
- package/dist/commands/addTask.d.ts +15 -0
- package/dist/commands/addTask.d.ts.map +1 -0
- package/dist/commands/addTask.js +101 -0
- package/dist/commands/addTask.js.map +1 -0
- package/dist/commands/help.d.ts.map +1 -1
- package/dist/commands/help.js +16 -5
- package/dist/commands/help.js.map +1 -1
- package/dist/commands/index.d.ts +3 -0
- package/dist/commands/index.d.ts.map +1 -1
- package/dist/commands/index.js +3 -0
- package/dist/commands/index.js.map +1 -1
- package/dist/commands/refreshBuiltin.d.ts +11 -0
- package/dist/commands/refreshBuiltin.d.ts.map +1 -0
- package/dist/commands/refreshBuiltin.js +37 -0
- package/dist/commands/refreshBuiltin.js.map +1 -0
- package/dist/commands/taskExecution.d.ts +9 -0
- package/dist/commands/taskExecution.d.ts.map +1 -1
- package/dist/commands/taskExecution.js +30 -2
- package/dist/commands/taskExecution.js.map +1 -1
- package/dist/commands/watchTasks.d.ts +12 -0
- package/dist/commands/watchTasks.d.ts.map +1 -0
- package/dist/commands/watchTasks.js +98 -0
- package/dist/commands/watchTasks.js.map +1 -0
- package/dist/resources/index.d.ts +5 -0
- package/dist/resources/index.d.ts.map +1 -1
- package/dist/resources/index.js +33 -9
- package/dist/resources/index.js.map +1 -1
- package/dist/task/display.d.ts.map +1 -1
- package/dist/task/display.js +19 -1
- package/dist/task/display.js.map +1 -1
- package/dist/task/index.d.ts +4 -0
- package/dist/task/index.d.ts.map +1 -1
- package/dist/task/index.js +4 -0
- package/dist/task/index.js.map +1 -1
- package/dist/task/parser.d.ts +33 -0
- package/dist/task/parser.d.ts.map +1 -0
- package/dist/task/parser.js +86 -0
- package/dist/task/parser.js.map +1 -0
- package/dist/task/runner.d.ts +6 -0
- package/dist/task/runner.d.ts.map +1 -1
- package/dist/task/runner.js +33 -42
- package/dist/task/runner.js.map +1 -1
- package/dist/task/schema.d.ts +32 -0
- package/dist/task/schema.d.ts.map +1 -0
- package/dist/task/schema.js +31 -0
- package/dist/task/schema.js.map +1 -0
- package/dist/task/watcher.d.ts +33 -0
- package/dist/task/watcher.d.ts.map +1 -0
- package/dist/task/watcher.js +69 -0
- package/dist/task/watcher.js.map +1 -0
- package/dist/task/worktree.d.ts +31 -0
- package/dist/task/worktree.d.ts.map +1 -0
- package/dist/task/worktree.js +112 -0
- package/dist/task/worktree.js.map +1 -0
- package/dist/utils/slug.d.ts +12 -0
- package/dist/utils/slug.d.ts.map +1 -0
- package/dist/utils/slug.js +18 -0
- package/dist/utils/slug.js.map +1 -0
- package/package.json +3 -2
- package/resources/global/ja/agents/default/architect.md +120 -0
- package/resources/global/ja/workflows/default.yaml +12 -0
package/dist/task/runner.js
CHANGED
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
* .takt/tasks/ ディレクトリ内のタスクファイルを読み込み、
|
|
5
5
|
* 順番に実行してレポートを生成する。
|
|
6
6
|
*
|
|
7
|
+
* Supports both .md (plain text) and .yaml/.yml (structured) task files.
|
|
8
|
+
*
|
|
7
9
|
* 使用方法:
|
|
8
10
|
* /task # タスク一覧を表示
|
|
9
11
|
* /task run # 次のタスクを実行
|
|
@@ -12,6 +14,7 @@
|
|
|
12
14
|
*/
|
|
13
15
|
import * as fs from 'node:fs';
|
|
14
16
|
import * as path from 'node:path';
|
|
17
|
+
import { parseTaskFiles, parseTaskFile } from './parser.js';
|
|
15
18
|
/**
|
|
16
19
|
* タスク実行管理クラス
|
|
17
20
|
*/
|
|
@@ -39,27 +42,9 @@ export class TaskRunner {
|
|
|
39
42
|
*/
|
|
40
43
|
listTasks() {
|
|
41
44
|
this.ensureDirs();
|
|
42
|
-
const tasks = [];
|
|
43
45
|
try {
|
|
44
|
-
const
|
|
45
|
-
|
|
46
|
-
.sort();
|
|
47
|
-
for (const file of files) {
|
|
48
|
-
const filePath = path.join(this.tasksDir, file);
|
|
49
|
-
try {
|
|
50
|
-
const content = fs.readFileSync(filePath, 'utf-8');
|
|
51
|
-
const stat = fs.statSync(filePath);
|
|
52
|
-
tasks.push({
|
|
53
|
-
filePath,
|
|
54
|
-
name: path.basename(file, '.md'),
|
|
55
|
-
content,
|
|
56
|
-
createdAt: stat.birthtime.toISOString(),
|
|
57
|
-
});
|
|
58
|
-
}
|
|
59
|
-
catch {
|
|
60
|
-
// ファイル読み込みエラーはスキップ
|
|
61
|
-
}
|
|
62
|
-
}
|
|
46
|
+
const parsed = parseTaskFiles(this.tasksDir);
|
|
47
|
+
return parsed.map(toTaskInfo);
|
|
63
48
|
}
|
|
64
49
|
catch (err) {
|
|
65
50
|
const nodeErr = err;
|
|
@@ -67,35 +52,30 @@ export class TaskRunner {
|
|
|
67
52
|
throw err; // 予期しないエラーは再スロー
|
|
68
53
|
}
|
|
69
54
|
// ENOENT は許容(ディレクトリ未作成)
|
|
55
|
+
return [];
|
|
70
56
|
}
|
|
71
|
-
return tasks;
|
|
72
57
|
}
|
|
73
58
|
/**
|
|
74
59
|
* 指定した名前のタスクを取得
|
|
60
|
+
* Searches for .yaml, .yml, and .md files in that order.
|
|
75
61
|
*/
|
|
76
62
|
getTask(name) {
|
|
77
63
|
this.ensureDirs();
|
|
78
|
-
const
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
};
|
|
91
|
-
}
|
|
92
|
-
catch (err) {
|
|
93
|
-
const nodeErr = err;
|
|
94
|
-
if (nodeErr.code !== 'ENOENT') {
|
|
95
|
-
throw err; // 予期しないエラーは再スロー
|
|
64
|
+
const extensions = ['.yaml', '.yml', '.md'];
|
|
65
|
+
for (const ext of extensions) {
|
|
66
|
+
const filePath = path.join(this.tasksDir, `${name}${ext}`);
|
|
67
|
+
if (!fs.existsSync(filePath)) {
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
try {
|
|
71
|
+
const parsed = parseTaskFile(filePath);
|
|
72
|
+
return toTaskInfo(parsed);
|
|
73
|
+
}
|
|
74
|
+
catch {
|
|
75
|
+
// Parse error: skip this extension
|
|
96
76
|
}
|
|
97
|
-
return null;
|
|
98
77
|
}
|
|
78
|
+
return null;
|
|
99
79
|
}
|
|
100
80
|
/**
|
|
101
81
|
* 次に実行すべきタスクを取得(最初のタスク)
|
|
@@ -119,8 +99,9 @@ export class TaskRunner {
|
|
|
119
99
|
// 完了ディレクトリにサブディレクトリを作成
|
|
120
100
|
const taskCompletedDir = path.join(this.completedDir, `${timestamp}_${result.task.name}`);
|
|
121
101
|
fs.mkdirSync(taskCompletedDir, { recursive: true });
|
|
122
|
-
//
|
|
123
|
-
const
|
|
102
|
+
// 元のタスクファイルを移動(元の拡張子を保持)
|
|
103
|
+
const originalExt = path.extname(result.task.filePath);
|
|
104
|
+
const completedTaskFile = path.join(taskCompletedDir, `${result.task.name}${originalExt}`);
|
|
124
105
|
fs.renameSync(result.task.filePath, completedTaskFile);
|
|
125
106
|
// レポートを生成
|
|
126
107
|
const reportFile = path.join(taskCompletedDir, 'report.md');
|
|
@@ -169,4 +150,14 @@ ${result.response}
|
|
|
169
150
|
`;
|
|
170
151
|
}
|
|
171
152
|
}
|
|
153
|
+
/** Convert ParsedTask to TaskInfo */
|
|
154
|
+
function toTaskInfo(parsed) {
|
|
155
|
+
return {
|
|
156
|
+
filePath: parsed.filePath,
|
|
157
|
+
name: parsed.name,
|
|
158
|
+
content: parsed.content,
|
|
159
|
+
createdAt: parsed.createdAt,
|
|
160
|
+
data: parsed.data,
|
|
161
|
+
};
|
|
162
|
+
}
|
|
172
163
|
//# sourceMappingURL=runner.js.map
|
package/dist/task/runner.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runner.js","sourceRoot":"","sources":["../../src/task/runner.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"runner.js","sourceRoot":"","sources":["../../src/task/runner.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Task YAML schema definition
|
|
3
|
+
*
|
|
4
|
+
* Zod schema for structured task files (.yaml/.yml)
|
|
5
|
+
*/
|
|
6
|
+
import { z } from 'zod/v4';
|
|
7
|
+
/**
|
|
8
|
+
* YAML task file schema
|
|
9
|
+
*
|
|
10
|
+
* Examples:
|
|
11
|
+
* task: "認証機能を追加する"
|
|
12
|
+
* worktree: true # .takt/worktrees/{timestamp}-{task-slug}/ に作成
|
|
13
|
+
* branch: "feat/add-auth" # オプション(省略時は自動生成)
|
|
14
|
+
* workflow: "default" # オプション(省略時はcurrent workflow)
|
|
15
|
+
*
|
|
16
|
+
* worktree patterns:
|
|
17
|
+
* - true: create at .takt/worktrees/{timestamp}-{task-slug}/
|
|
18
|
+
* - "/path/to/dir": create at specified path
|
|
19
|
+
* - omitted: no worktree (run in cwd)
|
|
20
|
+
*
|
|
21
|
+
* branch patterns:
|
|
22
|
+
* - "feat/xxx": use specified branch name
|
|
23
|
+
* - omitted: auto-generate as takt/{timestamp}-{task-slug}
|
|
24
|
+
*/
|
|
25
|
+
export declare const TaskFileSchema: z.ZodObject<{
|
|
26
|
+
task: z.ZodString;
|
|
27
|
+
worktree: z.ZodOptional<z.ZodUnion<readonly [z.ZodBoolean, z.ZodString]>>;
|
|
28
|
+
branch: z.ZodOptional<z.ZodString>;
|
|
29
|
+
workflow: z.ZodOptional<z.ZodString>;
|
|
30
|
+
}, z.core.$strip>;
|
|
31
|
+
export type TaskFileData = z.infer<typeof TaskFileSchema>;
|
|
32
|
+
//# sourceMappingURL=schema.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/task/schema.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,QAAQ,CAAC;AAE3B;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,cAAc;;;;;iBAKzB,CAAC;AAEH,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAC"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Task YAML schema definition
|
|
3
|
+
*
|
|
4
|
+
* Zod schema for structured task files (.yaml/.yml)
|
|
5
|
+
*/
|
|
6
|
+
import { z } from 'zod/v4';
|
|
7
|
+
/**
|
|
8
|
+
* YAML task file schema
|
|
9
|
+
*
|
|
10
|
+
* Examples:
|
|
11
|
+
* task: "認証機能を追加する"
|
|
12
|
+
* worktree: true # .takt/worktrees/{timestamp}-{task-slug}/ に作成
|
|
13
|
+
* branch: "feat/add-auth" # オプション(省略時は自動生成)
|
|
14
|
+
* workflow: "default" # オプション(省略時はcurrent workflow)
|
|
15
|
+
*
|
|
16
|
+
* worktree patterns:
|
|
17
|
+
* - true: create at .takt/worktrees/{timestamp}-{task-slug}/
|
|
18
|
+
* - "/path/to/dir": create at specified path
|
|
19
|
+
* - omitted: no worktree (run in cwd)
|
|
20
|
+
*
|
|
21
|
+
* branch patterns:
|
|
22
|
+
* - "feat/xxx": use specified branch name
|
|
23
|
+
* - omitted: auto-generate as takt/{timestamp}-{task-slug}
|
|
24
|
+
*/
|
|
25
|
+
export const TaskFileSchema = z.object({
|
|
26
|
+
task: z.string().min(1),
|
|
27
|
+
worktree: z.union([z.boolean(), z.string()]).optional(),
|
|
28
|
+
branch: z.string().optional(),
|
|
29
|
+
workflow: z.string().optional(),
|
|
30
|
+
});
|
|
31
|
+
//# sourceMappingURL=schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/task/schema.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,QAAQ,CAAC;AAE3B;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,CAAC,MAAM,CAAC;IACrC,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACvB,QAAQ,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,QAAQ,EAAE;IACvD,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC7B,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CAChC,CAAC,CAAC"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Task directory watcher
|
|
3
|
+
*
|
|
4
|
+
* Polls .takt/tasks/ for new task files and invokes a callback when found.
|
|
5
|
+
* Uses polling (not fs.watch) for cross-platform reliability.
|
|
6
|
+
*/
|
|
7
|
+
import { type TaskInfo } from './runner.js';
|
|
8
|
+
export interface TaskWatcherOptions {
|
|
9
|
+
/** Polling interval in milliseconds (default: 2000) */
|
|
10
|
+
pollInterval?: number;
|
|
11
|
+
}
|
|
12
|
+
export declare class TaskWatcher {
|
|
13
|
+
private runner;
|
|
14
|
+
private pollInterval;
|
|
15
|
+
private running;
|
|
16
|
+
private abortController;
|
|
17
|
+
constructor(projectDir: string, options?: TaskWatcherOptions);
|
|
18
|
+
/**
|
|
19
|
+
* Start watching for tasks.
|
|
20
|
+
* Resolves only when stop() is called.
|
|
21
|
+
*/
|
|
22
|
+
watch(onTask: (task: TaskInfo) => Promise<void>): Promise<void>;
|
|
23
|
+
/** Stop watching */
|
|
24
|
+
stop(): void;
|
|
25
|
+
/** Whether the watcher is currently active */
|
|
26
|
+
isRunning(): boolean;
|
|
27
|
+
/**
|
|
28
|
+
* Sleep with abort support.
|
|
29
|
+
* Resolves early if stop() is called.
|
|
30
|
+
*/
|
|
31
|
+
private sleep;
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=watcher.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"watcher.d.ts","sourceRoot":"","sources":["../../src/task/watcher.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAc,KAAK,QAAQ,EAAE,MAAM,aAAa,CAAC;AAIxD,MAAM,WAAW,kBAAkB;IACjC,uDAAuD;IACvD,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAID,qBAAa,WAAW;IACtB,OAAO,CAAC,MAAM,CAAa;IAC3B,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,eAAe,CAAgC;gBAE3C,UAAU,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,kBAAkB;IAK5D;;;OAGG;IACG,KAAK,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,QAAQ,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAuBrE,oBAAoB;IACpB,IAAI,IAAI,IAAI;IAKZ,8CAA8C;IAC9C,SAAS,IAAI,OAAO;IAIpB;;;OAGG;IACH,OAAO,CAAC,KAAK;CAiBd"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Task directory watcher
|
|
3
|
+
*
|
|
4
|
+
* Polls .takt/tasks/ for new task files and invokes a callback when found.
|
|
5
|
+
* Uses polling (not fs.watch) for cross-platform reliability.
|
|
6
|
+
*/
|
|
7
|
+
import { createLogger } from '../utils/debug.js';
|
|
8
|
+
import { TaskRunner } from './runner.js';
|
|
9
|
+
const log = createLogger('watcher');
|
|
10
|
+
const DEFAULT_POLL_INTERVAL = 2000;
|
|
11
|
+
export class TaskWatcher {
|
|
12
|
+
runner;
|
|
13
|
+
pollInterval;
|
|
14
|
+
running = false;
|
|
15
|
+
abortController = null;
|
|
16
|
+
constructor(projectDir, options) {
|
|
17
|
+
this.runner = new TaskRunner(projectDir);
|
|
18
|
+
this.pollInterval = options?.pollInterval ?? DEFAULT_POLL_INTERVAL;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Start watching for tasks.
|
|
22
|
+
* Resolves only when stop() is called.
|
|
23
|
+
*/
|
|
24
|
+
async watch(onTask) {
|
|
25
|
+
this.running = true;
|
|
26
|
+
this.abortController = new AbortController();
|
|
27
|
+
log.info('Watch started', { pollInterval: this.pollInterval });
|
|
28
|
+
while (this.running) {
|
|
29
|
+
const task = this.runner.getNextTask();
|
|
30
|
+
if (task) {
|
|
31
|
+
log.info('Task found', { name: task.name });
|
|
32
|
+
await onTask(task);
|
|
33
|
+
// After task execution, immediately check for next task (no sleep)
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
// No tasks: wait before next poll
|
|
37
|
+
await this.sleep(this.pollInterval);
|
|
38
|
+
}
|
|
39
|
+
log.info('Watch stopped');
|
|
40
|
+
}
|
|
41
|
+
/** Stop watching */
|
|
42
|
+
stop() {
|
|
43
|
+
this.running = false;
|
|
44
|
+
this.abortController?.abort();
|
|
45
|
+
}
|
|
46
|
+
/** Whether the watcher is currently active */
|
|
47
|
+
isRunning() {
|
|
48
|
+
return this.running;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Sleep with abort support.
|
|
52
|
+
* Resolves early if stop() is called.
|
|
53
|
+
*/
|
|
54
|
+
sleep(ms) {
|
|
55
|
+
return new Promise((resolve) => {
|
|
56
|
+
const signal = this.abortController?.signal;
|
|
57
|
+
if (signal?.aborted) {
|
|
58
|
+
resolve();
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
const timer = setTimeout(resolve, ms);
|
|
62
|
+
signal?.addEventListener('abort', () => {
|
|
63
|
+
clearTimeout(timer);
|
|
64
|
+
resolve();
|
|
65
|
+
}, { once: true });
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=watcher.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"watcher.js","sourceRoot":"","sources":["../../src/task/watcher.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,UAAU,EAAiB,MAAM,aAAa,CAAC;AAExD,MAAM,GAAG,GAAG,YAAY,CAAC,SAAS,CAAC,CAAC;AAOpC,MAAM,qBAAqB,GAAG,IAAI,CAAC;AAEnC,MAAM,OAAO,WAAW;IACd,MAAM,CAAa;IACnB,YAAY,CAAS;IACrB,OAAO,GAAG,KAAK,CAAC;IAChB,eAAe,GAA2B,IAAI,CAAC;IAEvD,YAAY,UAAkB,EAAE,OAA4B;QAC1D,IAAI,CAAC,MAAM,GAAG,IAAI,UAAU,CAAC,UAAU,CAAC,CAAC;QACzC,IAAI,CAAC,YAAY,GAAG,OAAO,EAAE,YAAY,IAAI,qBAAqB,CAAC;IACrE,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,KAAK,CAAC,MAAyC;QACnD,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;QACpB,IAAI,CAAC,eAAe,GAAG,IAAI,eAAe,EAAE,CAAC;QAE7C,GAAG,CAAC,IAAI,CAAC,eAAe,EAAE,EAAE,YAAY,EAAE,IAAI,CAAC,YAAY,EAAE,CAAC,CAAC;QAE/D,OAAO,IAAI,CAAC,OAAO,EAAE,CAAC;YACpB,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC;YAEvC,IAAI,IAAI,EAAE,CAAC;gBACT,GAAG,CAAC,IAAI,CAAC,YAAY,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;gBAC5C,MAAM,MAAM,CAAC,IAAI,CAAC,CAAC;gBACnB,mEAAmE;gBACnE,SAAS;YACX,CAAC;YAED,kCAAkC;YAClC,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QACtC,CAAC;QAED,GAAG,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;IAC5B,CAAC;IAED,oBAAoB;IACpB,IAAI;QACF,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC;QACrB,IAAI,CAAC,eAAe,EAAE,KAAK,EAAE,CAAC;IAChC,CAAC;IAED,8CAA8C;IAC9C,SAAS;QACP,OAAO,IAAI,CAAC,OAAO,CAAC;IACtB,CAAC;IAED;;;OAGG;IACK,KAAK,CAAC,EAAU;QACtB,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;YAC7B,MAAM,MAAM,GAAG,IAAI,CAAC,eAAe,EAAE,MAAM,CAAC;YAE5C,IAAI,MAAM,EAAE,OAAO,EAAE,CAAC;gBACpB,OAAO,EAAE,CAAC;gBACV,OAAO;YACT,CAAC;YAED,MAAM,KAAK,GAAG,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;YAEtC,MAAM,EAAE,gBAAgB,CAAC,OAAO,EAAE,GAAG,EAAE;gBACrC,YAAY,CAAC,KAAK,CAAC,CAAC;gBACpB,OAAO,EAAE,CAAC;YACZ,CAAC,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;QACrB,CAAC,CAAC,CAAC;IACL,CAAC;CACF"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Git worktree management
|
|
3
|
+
*
|
|
4
|
+
* Creates and removes git worktrees for task isolation.
|
|
5
|
+
*/
|
|
6
|
+
export interface WorktreeOptions {
|
|
7
|
+
/** worktree setting: true = auto path, string = custom path */
|
|
8
|
+
worktree: boolean | string;
|
|
9
|
+
/** Branch name (optional, auto-generated if omitted) */
|
|
10
|
+
branch?: string;
|
|
11
|
+
/** Task slug for auto-generated paths/branches */
|
|
12
|
+
taskSlug: string;
|
|
13
|
+
}
|
|
14
|
+
export interface WorktreeResult {
|
|
15
|
+
/** Absolute path to the worktree */
|
|
16
|
+
path: string;
|
|
17
|
+
/** Branch name used */
|
|
18
|
+
branch: string;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Create a git worktree for a task
|
|
22
|
+
*
|
|
23
|
+
* @returns WorktreeResult with path and branch
|
|
24
|
+
* @throws Error if git worktree creation fails
|
|
25
|
+
*/
|
|
26
|
+
export declare function createWorktree(projectDir: string, options: WorktreeOptions): WorktreeResult;
|
|
27
|
+
/**
|
|
28
|
+
* Remove a git worktree
|
|
29
|
+
*/
|
|
30
|
+
export declare function removeWorktree(projectDir: string, worktreePath: string): void;
|
|
31
|
+
//# sourceMappingURL=worktree.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"worktree.d.ts","sourceRoot":"","sources":["../../src/task/worktree.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAWH,MAAM,WAAW,eAAe;IAC9B,+DAA+D;IAC/D,QAAQ,EAAE,OAAO,GAAG,MAAM,CAAC;IAC3B,wDAAwD;IACxD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,kDAAkD;IAClD,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,cAAc;IAC7B,oCAAoC;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,uBAAuB;IACvB,MAAM,EAAE,MAAM,CAAC;CAChB;AAgED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,eAAe,GAAG,cAAc,CAyB3F;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,UAAU,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,IAAI,CAY7E"}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Git worktree management
|
|
3
|
+
*
|
|
4
|
+
* Creates and removes git worktrees for task isolation.
|
|
5
|
+
*/
|
|
6
|
+
import * as fs from 'node:fs';
|
|
7
|
+
import * as path from 'node:path';
|
|
8
|
+
import { execFileSync } from 'node:child_process';
|
|
9
|
+
import { createLogger } from '../utils/debug.js';
|
|
10
|
+
import { slugify } from '../utils/slug.js';
|
|
11
|
+
import { isPathSafe } from '../config/paths.js';
|
|
12
|
+
const log = createLogger('worktree');
|
|
13
|
+
/**
|
|
14
|
+
* Generate a timestamp string for paths/branches
|
|
15
|
+
*/
|
|
16
|
+
function generateTimestamp() {
|
|
17
|
+
return new Date().toISOString().replace(/[:.]/g, '').slice(0, 15);
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Resolve the worktree path based on options.
|
|
21
|
+
* Validates that the resolved path stays within the project directory.
|
|
22
|
+
*
|
|
23
|
+
* @throws Error if the resolved path escapes projectDir (path traversal)
|
|
24
|
+
*/
|
|
25
|
+
function resolveWorktreePath(projectDir, options) {
|
|
26
|
+
if (typeof options.worktree === 'string') {
|
|
27
|
+
const resolved = path.isAbsolute(options.worktree)
|
|
28
|
+
? options.worktree
|
|
29
|
+
: path.resolve(projectDir, options.worktree);
|
|
30
|
+
if (!isPathSafe(projectDir, resolved)) {
|
|
31
|
+
throw new Error(`Worktree path escapes project directory: ${options.worktree}`);
|
|
32
|
+
}
|
|
33
|
+
return resolved;
|
|
34
|
+
}
|
|
35
|
+
// worktree: true → .takt/worktrees/{timestamp}-{task-slug}/
|
|
36
|
+
const timestamp = generateTimestamp();
|
|
37
|
+
const slug = slugify(options.taskSlug);
|
|
38
|
+
const dirName = slug ? `${timestamp}-${slug}` : timestamp;
|
|
39
|
+
return path.join(projectDir, '.takt', 'worktrees', dirName);
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Resolve the branch name based on options
|
|
43
|
+
*/
|
|
44
|
+
function resolveBranchName(options) {
|
|
45
|
+
if (options.branch) {
|
|
46
|
+
return options.branch;
|
|
47
|
+
}
|
|
48
|
+
// Auto-generate: takt/{timestamp}-{task-slug}
|
|
49
|
+
const timestamp = generateTimestamp();
|
|
50
|
+
const slug = slugify(options.taskSlug);
|
|
51
|
+
return slug ? `takt/${timestamp}-${slug}` : `takt/${timestamp}`;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Check if a git branch exists
|
|
55
|
+
*/
|
|
56
|
+
function branchExists(projectDir, branch) {
|
|
57
|
+
try {
|
|
58
|
+
execFileSync('git', ['rev-parse', '--verify', branch], {
|
|
59
|
+
cwd: projectDir,
|
|
60
|
+
stdio: 'pipe',
|
|
61
|
+
});
|
|
62
|
+
return true;
|
|
63
|
+
}
|
|
64
|
+
catch {
|
|
65
|
+
return false;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Create a git worktree for a task
|
|
70
|
+
*
|
|
71
|
+
* @returns WorktreeResult with path and branch
|
|
72
|
+
* @throws Error if git worktree creation fails
|
|
73
|
+
*/
|
|
74
|
+
export function createWorktree(projectDir, options) {
|
|
75
|
+
const worktreePath = resolveWorktreePath(projectDir, options);
|
|
76
|
+
const branch = resolveBranchName(options);
|
|
77
|
+
log.info('Creating worktree', { path: worktreePath, branch });
|
|
78
|
+
// Ensure parent directory exists
|
|
79
|
+
fs.mkdirSync(path.dirname(worktreePath), { recursive: true });
|
|
80
|
+
// Create worktree (use execFileSync to avoid shell injection)
|
|
81
|
+
if (branchExists(projectDir, branch)) {
|
|
82
|
+
execFileSync('git', ['worktree', 'add', worktreePath, branch], {
|
|
83
|
+
cwd: projectDir,
|
|
84
|
+
stdio: 'pipe',
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
execFileSync('git', ['worktree', 'add', '-b', branch, worktreePath], {
|
|
89
|
+
cwd: projectDir,
|
|
90
|
+
stdio: 'pipe',
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
log.info('Worktree created', { path: worktreePath, branch });
|
|
94
|
+
return { path: worktreePath, branch };
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Remove a git worktree
|
|
98
|
+
*/
|
|
99
|
+
export function removeWorktree(projectDir, worktreePath) {
|
|
100
|
+
log.info('Removing worktree', { path: worktreePath });
|
|
101
|
+
try {
|
|
102
|
+
execFileSync('git', ['worktree', 'remove', worktreePath, '--force'], {
|
|
103
|
+
cwd: projectDir,
|
|
104
|
+
stdio: 'pipe',
|
|
105
|
+
});
|
|
106
|
+
log.info('Worktree removed', { path: worktreePath });
|
|
107
|
+
}
|
|
108
|
+
catch (err) {
|
|
109
|
+
log.error('Failed to remove worktree', { path: worktreePath, error: String(err) });
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
//# sourceMappingURL=worktree.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"worktree.js","sourceRoot":"","sources":["../../src/task/worktree.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Text slugification utility
|
|
3
|
+
*
|
|
4
|
+
* Converts text into URL/filename-safe slugs.
|
|
5
|
+
* Supports ASCII alphanumerics and CJK characters.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Convert text into a slug for use in filenames, paths, and branch names.
|
|
9
|
+
* Preserves CJK characters (U+3000-9FFF, FF00-FFEF).
|
|
10
|
+
*/
|
|
11
|
+
export declare function slugify(text: string): string;
|
|
12
|
+
//# sourceMappingURL=slug.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"slug.d.ts","sourceRoot":"","sources":["../../src/utils/slug.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;;GAGG;AACH,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAM5C"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Text slugification utility
|
|
3
|
+
*
|
|
4
|
+
* Converts text into URL/filename-safe slugs.
|
|
5
|
+
* Supports ASCII alphanumerics and CJK characters.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Convert text into a slug for use in filenames, paths, and branch names.
|
|
9
|
+
* Preserves CJK characters (U+3000-9FFF, FF00-FFEF).
|
|
10
|
+
*/
|
|
11
|
+
export function slugify(text) {
|
|
12
|
+
return text
|
|
13
|
+
.toLowerCase()
|
|
14
|
+
.replace(/[^a-z0-9\u3000-\u9fff\uff00-\uffef]+/g, '-')
|
|
15
|
+
.replace(/^-+|-+$/g, '')
|
|
16
|
+
.slice(0, 50);
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=slug.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"slug.js","sourceRoot":"","sources":["../../src/utils/slug.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;;GAGG;AACH,MAAM,UAAU,OAAO,CAAC,IAAY;IAClC,OAAO,IAAI;SACR,WAAW,EAAE;SACb,OAAO,CAAC,uCAAuC,EAAE,GAAG,CAAC;SACrD,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC;SACvB,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;AAClB,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "takt",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "TAKT: Task Agent Koordination Tool - AI Agent Workflow Orchestration",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -15,7 +15,8 @@
|
|
|
15
15
|
"test": "vitest run",
|
|
16
16
|
"test:watch": "vitest",
|
|
17
17
|
"lint": "eslint src/",
|
|
18
|
-
"prepublishOnly": "npm run lint && npm run build && npm run test"
|
|
18
|
+
"prepublishOnly": "npm run lint && npm run build && npm run test",
|
|
19
|
+
"postversion": "git push --follow-tags"
|
|
19
20
|
},
|
|
20
21
|
"keywords": [
|
|
21
22
|
"claude",
|