create-claude-pipeline 0.3.0 → 0.3.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/bin/cli.js +13 -6
- package/package.json +1 -1
- package/template/.claude-pipeline/runner/dist/context-watcher.d.ts +10 -6
- package/template/.claude-pipeline/runner/dist/context-watcher.js +53 -40
- package/template/.claude-pipeline/runner/dist/context-watcher.js.map +1 -1
- package/template/.claude-pipeline/runner/dist/pipeline-runner.js +8 -0
- package/template/.claude-pipeline/runner/dist/pipeline-runner.js.map +1 -1
- package/template/.claude-pipeline/runner/src/context-watcher.ts +58 -40
- package/template/.claude-pipeline/runner/src/pipeline-runner.ts +8 -0
- package/template/CLAUDE.md +22 -2
package/bin/cli.js
CHANGED
|
@@ -275,7 +275,7 @@ async function startDashboard(targetDir) {
|
|
|
275
275
|
var TOTAL_STEPS = 6;
|
|
276
276
|
function showHelp() {
|
|
277
277
|
console.log(`
|
|
278
|
-
Usage: npx create-claude-pipeline
|
|
278
|
+
Usage: npx create-claude-pipeline [options]
|
|
279
279
|
|
|
280
280
|
Claude Code \uD30C\uC774\uD504\uB77C\uC778 \uC2DC\uC2A4\uD15C\uC744 \uD604\uC7AC \uB514\uB809\uD1A0\uB9AC\uC5D0 \uC124\uCE58\uD558\uACE0 \uB300\uC2DC\uBCF4\uB4DC\uB97C \uC2E4\uD589\uD569\uB2C8\uB2E4.
|
|
281
281
|
|
|
@@ -283,8 +283,9 @@ function showHelp() {
|
|
|
283
283
|
\uC7AC\uC2E4\uD589: \uB300\uC2DC\uBCF4\uB4DC\uB9CC \uC2E4\uD589
|
|
284
284
|
|
|
285
285
|
Options:
|
|
286
|
-
--
|
|
287
|
-
--
|
|
286
|
+
--update, -u \uD30C\uC774\uD504\uB77C\uC778 \uC2DC\uC2A4\uD15C\uC744 \uCD5C\uC2E0 \uBC84\uC804\uC73C\uB85C \uC5C5\uB370\uC774\uD2B8
|
|
287
|
+
--help \uC774 \uB3C4\uC6C0\uB9D0 \uD45C\uC2DC
|
|
288
|
+
--version \uBC84\uC804 \uD45C\uC2DC
|
|
288
289
|
`);
|
|
289
290
|
}
|
|
290
291
|
async function showVersion() {
|
|
@@ -308,11 +309,17 @@ async function main() {
|
|
|
308
309
|
}
|
|
309
310
|
const cwd = process.cwd();
|
|
310
311
|
const dashboardPkg = import_path7.default.join(cwd, ".claude-pipeline", "dashboard", "package.json");
|
|
312
|
+
const forceUpdate = args.includes("--update") || args.includes("-u");
|
|
311
313
|
if (await import_fs_extra5.default.pathExists(dashboardPkg)) {
|
|
314
|
+
if (!forceUpdate) {
|
|
315
|
+
console.log();
|
|
316
|
+
success("\uC774\uBBF8 \uC124\uCE58\uB428 \u2014 \uB300\uC2DC\uBCF4\uB4DC\uB9CC \uC2E4\uD589\uD569\uB2C8\uB2E4");
|
|
317
|
+
success("\uC5C5\uB370\uC774\uD2B8\uD558\uB824\uBA74: npx create-claude-pipeline --update");
|
|
318
|
+
await startDashboard(cwd);
|
|
319
|
+
return;
|
|
320
|
+
}
|
|
312
321
|
console.log();
|
|
313
|
-
success("\uC774\
|
|
314
|
-
await startDashboard(cwd);
|
|
315
|
-
return;
|
|
322
|
+
success("\uC5C5\uB370\uC774\uD2B8 \uBAA8\uB4DC \u2014 \uD30C\uC77C\uC744 \uB36E\uC5B4\uC4F0\uACE0 \uC7AC\uC124\uCE58\uD569\uB2C8\uB2E4");
|
|
316
323
|
}
|
|
317
324
|
banner();
|
|
318
325
|
step(1, TOTAL_STEPS, "\uD30C\uC77C \uBCF5\uC0AC \uC911...");
|
package/package.json
CHANGED
|
@@ -1,19 +1,23 @@
|
|
|
1
1
|
import type { StateManager } from "./state-manager.js";
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
4
|
-
*
|
|
3
|
+
* Watches for context file creation in TWO locations:
|
|
4
|
+
* 1. pipelines/{id}/context/ — primary (dashboard-aware Claude)
|
|
5
|
+
* 2. project-root/context/ — fallback (Claude ignoring dashboard instructions)
|
|
6
|
+
*
|
|
7
|
+
* When a file is found at project root, it's copied into the pipeline dir.
|
|
5
8
|
*/
|
|
6
9
|
export declare class ContextWatcher {
|
|
7
10
|
private stateManager;
|
|
8
|
-
private
|
|
9
|
-
private
|
|
11
|
+
private pipelineContextDir;
|
|
12
|
+
private rootContextDir;
|
|
10
13
|
private seenFiles;
|
|
11
14
|
private lastSignalTime;
|
|
15
|
+
private intervals;
|
|
12
16
|
constructor(stateManager: StateManager, pipelinesDir: string, pipelineId: string);
|
|
13
|
-
/** Call this whenever SignalWatcher processes a signal */
|
|
14
17
|
notifySignalProcessed(): void;
|
|
15
18
|
start(): void;
|
|
16
19
|
stop(): void;
|
|
17
|
-
private
|
|
20
|
+
private scanDir;
|
|
18
21
|
private pollDirectory;
|
|
22
|
+
private handleFile;
|
|
19
23
|
}
|
|
@@ -18,79 +18,92 @@ const CONTEXT_FILE_PHASES = {
|
|
|
18
18
|
"security_report.md": 4,
|
|
19
19
|
};
|
|
20
20
|
/**
|
|
21
|
-
*
|
|
22
|
-
*
|
|
21
|
+
* Watches for context file creation in TWO locations:
|
|
22
|
+
* 1. pipelines/{id}/context/ — primary (dashboard-aware Claude)
|
|
23
|
+
* 2. project-root/context/ — fallback (Claude ignoring dashboard instructions)
|
|
24
|
+
*
|
|
25
|
+
* When a file is found at project root, it's copied into the pipeline dir.
|
|
23
26
|
*/
|
|
24
27
|
export class ContextWatcher {
|
|
25
28
|
stateManager;
|
|
26
|
-
|
|
27
|
-
|
|
29
|
+
pipelineContextDir;
|
|
30
|
+
rootContextDir;
|
|
28
31
|
seenFiles = new Set();
|
|
29
32
|
lastSignalTime = 0;
|
|
33
|
+
intervals = [];
|
|
30
34
|
constructor(stateManager, pipelinesDir, pipelineId) {
|
|
31
35
|
this.stateManager = stateManager;
|
|
32
|
-
this.
|
|
36
|
+
this.pipelineContextDir = path.join(pipelinesDir, pipelineId, "context");
|
|
37
|
+
// Project root is one level up from pipelines dir
|
|
38
|
+
this.rootContextDir = path.join(pipelinesDir, "..", "context");
|
|
33
39
|
}
|
|
34
|
-
/** Call this whenever SignalWatcher processes a signal */
|
|
35
40
|
notifySignalProcessed() {
|
|
36
41
|
this.lastSignalTime = Date.now();
|
|
37
42
|
}
|
|
38
43
|
start() {
|
|
39
|
-
fs.mkdirSync(this.
|
|
40
|
-
// Scan existing files
|
|
44
|
+
fs.mkdirSync(this.pipelineContextDir, { recursive: true });
|
|
45
|
+
// Scan existing files
|
|
46
|
+
this.scanDir(this.pipelineContextDir);
|
|
47
|
+
this.scanDir(this.rootContextDir);
|
|
48
|
+
// Poll both directories
|
|
49
|
+
this.intervals.push(setInterval(() => this.pollDirectory(this.pipelineContextDir, false), 2000), setInterval(() => this.pollDirectory(this.rootContextDir, true), 2000));
|
|
50
|
+
}
|
|
51
|
+
stop() {
|
|
52
|
+
for (const interval of this.intervals) {
|
|
53
|
+
clearInterval(interval);
|
|
54
|
+
}
|
|
55
|
+
this.intervals = [];
|
|
56
|
+
}
|
|
57
|
+
scanDir(dir) {
|
|
41
58
|
try {
|
|
42
|
-
const
|
|
43
|
-
for (const file of
|
|
59
|
+
const files = fs.readdirSync(dir);
|
|
60
|
+
for (const file of files) {
|
|
44
61
|
this.seenFiles.add(file);
|
|
45
62
|
}
|
|
46
63
|
}
|
|
47
64
|
catch {
|
|
48
|
-
// directory
|
|
65
|
+
// directory may not exist
|
|
49
66
|
}
|
|
67
|
+
}
|
|
68
|
+
pollDirectory(dir, isRootFallback) {
|
|
50
69
|
try {
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
70
|
+
if (!fs.existsSync(dir))
|
|
71
|
+
return;
|
|
72
|
+
const files = fs.readdirSync(dir);
|
|
73
|
+
for (const file of files) {
|
|
74
|
+
this.handleFile(file, dir, isRootFallback);
|
|
75
|
+
}
|
|
56
76
|
}
|
|
57
77
|
catch {
|
|
58
|
-
//
|
|
59
|
-
setInterval(() => this.pollDirectory(), 3000);
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
stop() {
|
|
63
|
-
if (this.watcher) {
|
|
64
|
-
this.watcher.close();
|
|
65
|
-
this.watcher = null;
|
|
78
|
+
// directory may not exist yet
|
|
66
79
|
}
|
|
67
80
|
}
|
|
68
|
-
handleFile(filename) {
|
|
81
|
+
handleFile(filename, sourceDir, isRootFallback) {
|
|
69
82
|
if (this.seenFiles.has(filename))
|
|
70
83
|
return;
|
|
71
|
-
|
|
72
|
-
const filePath = path.join(this.contextDir, filename);
|
|
84
|
+
const filePath = path.join(sourceDir, filename);
|
|
73
85
|
if (!fs.existsSync(filePath))
|
|
74
86
|
return;
|
|
75
87
|
this.seenFiles.add(filename);
|
|
76
|
-
//
|
|
88
|
+
// If found at project root, copy to pipeline context dir
|
|
89
|
+
if (isRootFallback) {
|
|
90
|
+
const destPath = path.join(this.pipelineContextDir, filename);
|
|
91
|
+
if (!fs.existsSync(destPath)) {
|
|
92
|
+
try {
|
|
93
|
+
fs.copyFileSync(filePath, destPath);
|
|
94
|
+
}
|
|
95
|
+
catch {
|
|
96
|
+
// copy may fail if file is being written
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
// Skip state update if SignalWatcher was active recently
|
|
77
101
|
if (Date.now() - this.lastSignalTime < 5000)
|
|
78
102
|
return;
|
|
79
103
|
const phase = CONTEXT_FILE_PHASES[filename];
|
|
80
104
|
if (phase !== undefined) {
|
|
81
105
|
this.stateManager.addOutput(`context/${filename}`, phase);
|
|
82
|
-
this.stateManager.addActivity("system", "info", `산출물 감지: context/${filename} (Phase ${phase})`);
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
pollDirectory() {
|
|
86
|
-
try {
|
|
87
|
-
const files = fs.readdirSync(this.contextDir);
|
|
88
|
-
for (const file of files) {
|
|
89
|
-
this.handleFile(file);
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
catch {
|
|
93
|
-
// directory may not exist yet
|
|
106
|
+
this.stateManager.addActivity("system", "info", `산출물 감지: context/${filename} (Phase ${phase})${isRootFallback ? " [루트에서 복사됨]" : ""}`);
|
|
94
107
|
}
|
|
95
108
|
}
|
|
96
109
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context-watcher.js","sourceRoot":"","sources":["../src/context-watcher.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;AAGxB,+DAA+D;AAC/D,MAAM,mBAAmB,GAA2B;IAClD,oBAAoB,EAAE,CAAC;IACvB,YAAY,EAAE,CAAC;IACf,cAAc,EAAE,CAAC;IACjB,mBAAmB,EAAE,CAAC;IACtB,gBAAgB,EAAE,CAAC;IACnB,WAAW,EAAE,CAAC;IACd,eAAe,EAAE,CAAC;IAClB,eAAe,EAAE,CAAC;IAClB,kBAAkB,EAAE,CAAC;IACrB,eAAe,EAAE,CAAC;IAClB,gBAAgB,EAAE,CAAC;IACnB,mBAAmB,EAAE,CAAC;IACtB,cAAc,EAAE,CAAC;IACjB,oBAAoB,EAAE,CAAC;CACxB,CAAC;AAEF
|
|
1
|
+
{"version":3,"file":"context-watcher.js","sourceRoot":"","sources":["../src/context-watcher.ts"],"names":[],"mappings":"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"}
|
|
@@ -39,6 +39,14 @@ function buildPrompt(requirements, pipelineId) {
|
|
|
39
39
|
"",
|
|
40
40
|
"중요: 이 세션은 파이프라인 대시보드에서 실행됩니다.",
|
|
41
41
|
'CLAUDE.md의 "Pipeline Dashboard Integration" 섹션을 반드시 따르세요.',
|
|
42
|
+
"",
|
|
43
|
+
"특히 context 파일 경로에 주의하세요:",
|
|
44
|
+
`- 모든 산출물(context 파일)은 pipelines/${pipelineId}/context/ 에 생성`,
|
|
45
|
+
`- 시그널 파일은 pipelines/${pipelineId}/signals/ 에 생성`,
|
|
46
|
+
`- 예: pipelines/${pipelineId}/context/00_requirements.md`,
|
|
47
|
+
`- 예: pipelines/${pipelineId}/context/01_plan.md`,
|
|
48
|
+
"",
|
|
49
|
+
"절대 프로젝트 루트의 context/ 폴더에 파일을 만들지 마세요.",
|
|
42
50
|
].join("\n");
|
|
43
51
|
}
|
|
44
52
|
// ── Main ────────────────────────────────────────────────────────────
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pipeline-runner.js","sourceRoot":"","sources":["../src/pipeline-runner.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAE3D,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC;AAC5C,MAAM,aAAa,GAAG,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC;AAChD,MAAM,YAAY,GAAG,OAAO,CAAC,GAAG,CAAC,qBAAqB,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;AAEhF,IAAI,CAAC,WAAW,IAAI,CAAC,aAAa,EAAE,CAAC;IACnC,OAAO,CAAC,KAAK,CAAC,kEAAkE,CAAC,CAAC;IAClF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,IAAI,CAAC,YAAY,EAAE,CAAC;IAClB,OAAO,CAAC,KAAK,CAAC,0BAA0B,CAAC,CAAC;IAC1C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,EAAE,IAAI,CAAC,CAAC;AACtD,MAAM,eAAe,GAAG,IAAI,eAAe,EAAE,CAAC;AAE9C,uEAAuE;AACvE,SAAS,cAAc;IACrB,IAAI,CAAC;QACH,QAAQ,CAAC,kBAAkB,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;QAChE,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,uEAAuE;AACvE,SAAS,WAAW,CAAC,YAAoB,EAAE,UAAkB;IAC3D,OAAO;QACL,0BAA0B;QAC1B,EAAE;QACF,gBAAgB,UAAU,EAAE;QAC5B,EAAE;QACF,OAAO;QACP,YAAY;QACZ,EAAE;QACF,+BAA+B;QAC/B,2DAA2D;
|
|
1
|
+
{"version":3,"file":"pipeline-runner.js","sourceRoot":"","sources":["../src/pipeline-runner.ts"],"names":[],"mappings":"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"}
|
|
@@ -21,69 +21,98 @@ const CONTEXT_FILE_PHASES: Record<string, number> = {
|
|
|
21
21
|
};
|
|
22
22
|
|
|
23
23
|
/**
|
|
24
|
-
*
|
|
25
|
-
*
|
|
24
|
+
* Watches for context file creation in TWO locations:
|
|
25
|
+
* 1. pipelines/{id}/context/ — primary (dashboard-aware Claude)
|
|
26
|
+
* 2. project-root/context/ — fallback (Claude ignoring dashboard instructions)
|
|
27
|
+
*
|
|
28
|
+
* When a file is found at project root, it's copied into the pipeline dir.
|
|
26
29
|
*/
|
|
27
30
|
export class ContextWatcher {
|
|
28
|
-
private
|
|
29
|
-
private
|
|
31
|
+
private pipelineContextDir: string;
|
|
32
|
+
private rootContextDir: string;
|
|
30
33
|
private seenFiles = new Set<string>();
|
|
31
34
|
private lastSignalTime = 0;
|
|
35
|
+
private intervals: ReturnType<typeof setInterval>[] = [];
|
|
32
36
|
|
|
33
37
|
constructor(
|
|
34
38
|
private stateManager: StateManager,
|
|
35
39
|
pipelinesDir: string,
|
|
36
40
|
pipelineId: string,
|
|
37
41
|
) {
|
|
38
|
-
this.
|
|
42
|
+
this.pipelineContextDir = path.join(pipelinesDir, pipelineId, "context");
|
|
43
|
+
// Project root is one level up from pipelines dir
|
|
44
|
+
this.rootContextDir = path.join(pipelinesDir, "..", "context");
|
|
39
45
|
}
|
|
40
46
|
|
|
41
|
-
/** Call this whenever SignalWatcher processes a signal */
|
|
42
47
|
notifySignalProcessed(): void {
|
|
43
48
|
this.lastSignalTime = Date.now();
|
|
44
49
|
}
|
|
45
50
|
|
|
46
51
|
start(): void {
|
|
47
|
-
fs.mkdirSync(this.
|
|
52
|
+
fs.mkdirSync(this.pipelineContextDir, { recursive: true });
|
|
48
53
|
|
|
49
|
-
// Scan existing files
|
|
54
|
+
// Scan existing files
|
|
55
|
+
this.scanDir(this.pipelineContextDir);
|
|
56
|
+
this.scanDir(this.rootContextDir);
|
|
57
|
+
|
|
58
|
+
// Poll both directories
|
|
59
|
+
this.intervals.push(
|
|
60
|
+
setInterval(() => this.pollDirectory(this.pipelineContextDir, false), 2000),
|
|
61
|
+
setInterval(() => this.pollDirectory(this.rootContextDir, true), 2000),
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
stop(): void {
|
|
66
|
+
for (const interval of this.intervals) {
|
|
67
|
+
clearInterval(interval);
|
|
68
|
+
}
|
|
69
|
+
this.intervals = [];
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
private scanDir(dir: string): void {
|
|
50
73
|
try {
|
|
51
|
-
const
|
|
52
|
-
for (const file of
|
|
74
|
+
const files = fs.readdirSync(dir);
|
|
75
|
+
for (const file of files) {
|
|
53
76
|
this.seenFiles.add(file);
|
|
54
77
|
}
|
|
55
78
|
} catch {
|
|
56
|
-
// directory
|
|
79
|
+
// directory may not exist
|
|
57
80
|
}
|
|
81
|
+
}
|
|
58
82
|
|
|
83
|
+
private pollDirectory(dir: string, isRootFallback: boolean): void {
|
|
59
84
|
try {
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
85
|
+
if (!fs.existsSync(dir)) return;
|
|
86
|
+
const files = fs.readdirSync(dir);
|
|
87
|
+
for (const file of files) {
|
|
88
|
+
this.handleFile(file, dir, isRootFallback);
|
|
89
|
+
}
|
|
64
90
|
} catch {
|
|
65
|
-
//
|
|
66
|
-
setInterval(() => this.pollDirectory(), 3000);
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
stop(): void {
|
|
71
|
-
if (this.watcher) {
|
|
72
|
-
this.watcher.close();
|
|
73
|
-
this.watcher = null;
|
|
91
|
+
// directory may not exist yet
|
|
74
92
|
}
|
|
75
93
|
}
|
|
76
94
|
|
|
77
|
-
private handleFile(filename: string): void {
|
|
95
|
+
private handleFile(filename: string, sourceDir: string, isRootFallback: boolean): void {
|
|
78
96
|
if (this.seenFiles.has(filename)) return;
|
|
79
97
|
|
|
80
|
-
|
|
81
|
-
const filePath = path.join(this.contextDir, filename);
|
|
98
|
+
const filePath = path.join(sourceDir, filename);
|
|
82
99
|
if (!fs.existsSync(filePath)) return;
|
|
83
100
|
|
|
84
101
|
this.seenFiles.add(filename);
|
|
85
102
|
|
|
86
|
-
//
|
|
103
|
+
// If found at project root, copy to pipeline context dir
|
|
104
|
+
if (isRootFallback) {
|
|
105
|
+
const destPath = path.join(this.pipelineContextDir, filename);
|
|
106
|
+
if (!fs.existsSync(destPath)) {
|
|
107
|
+
try {
|
|
108
|
+
fs.copyFileSync(filePath, destPath);
|
|
109
|
+
} catch {
|
|
110
|
+
// copy may fail if file is being written
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// Skip state update if SignalWatcher was active recently
|
|
87
116
|
if (Date.now() - this.lastSignalTime < 5000) return;
|
|
88
117
|
|
|
89
118
|
const phase = CONTEXT_FILE_PHASES[filename];
|
|
@@ -92,19 +121,8 @@ export class ContextWatcher {
|
|
|
92
121
|
this.stateManager.addActivity(
|
|
93
122
|
"system",
|
|
94
123
|
"info",
|
|
95
|
-
`산출물 감지: context/${filename} (Phase ${phase})`,
|
|
124
|
+
`산출물 감지: context/${filename} (Phase ${phase})${isRootFallback ? " [루트에서 복사됨]" : ""}`,
|
|
96
125
|
);
|
|
97
126
|
}
|
|
98
127
|
}
|
|
99
|
-
|
|
100
|
-
private pollDirectory(): void {
|
|
101
|
-
try {
|
|
102
|
-
const files = fs.readdirSync(this.contextDir);
|
|
103
|
-
for (const file of files) {
|
|
104
|
-
this.handleFile(file);
|
|
105
|
-
}
|
|
106
|
-
} catch {
|
|
107
|
-
// directory may not exist yet
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
128
|
}
|
|
@@ -45,6 +45,14 @@ function buildPrompt(requirements: string, pipelineId: string): string {
|
|
|
45
45
|
"",
|
|
46
46
|
"중요: 이 세션은 파이프라인 대시보드에서 실행됩니다.",
|
|
47
47
|
'CLAUDE.md의 "Pipeline Dashboard Integration" 섹션을 반드시 따르세요.',
|
|
48
|
+
"",
|
|
49
|
+
"특히 context 파일 경로에 주의하세요:",
|
|
50
|
+
`- 모든 산출물(context 파일)은 pipelines/${pipelineId}/context/ 에 생성`,
|
|
51
|
+
`- 시그널 파일은 pipelines/${pipelineId}/signals/ 에 생성`,
|
|
52
|
+
`- 예: pipelines/${pipelineId}/context/00_requirements.md`,
|
|
53
|
+
`- 예: pipelines/${pipelineId}/context/01_plan.md`,
|
|
54
|
+
"",
|
|
55
|
+
"절대 프로젝트 루트의 context/ 폴더에 파일을 만들지 마세요.",
|
|
48
56
|
].join("\n");
|
|
49
57
|
}
|
|
50
58
|
|
package/template/CLAUDE.md
CHANGED
|
@@ -305,8 +305,28 @@ context/
|
|
|
305
305
|
## Pipeline Dashboard Integration
|
|
306
306
|
|
|
307
307
|
환경변수 `PIPELINE_ID`가 설정되어 있으면 **대시보드에서 실행 중**이다.
|
|
308
|
-
아래
|
|
309
|
-
|
|
308
|
+
아래 규칙을 반드시 따른다.
|
|
309
|
+
|
|
310
|
+
### context 파일 경로 (중요!)
|
|
311
|
+
|
|
312
|
+
대시보드 실행 시, **모든 context 파일은 파이프라인 전용 디렉토리에 생성한다:**
|
|
313
|
+
```
|
|
314
|
+
pipelines/$PIPELINE_ID/context/
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
즉, 일반 실행에서 `context/00_requirements.md`에 저장하던 파일을
|
|
318
|
+
대시보드 실행 시에는 `pipelines/$PIPELINE_ID/context/00_requirements.md`에 저장한다.
|
|
319
|
+
|
|
320
|
+
**모든 Phase의 산출물이 이 경로를 따라야 한다:**
|
|
321
|
+
- `pipelines/$PIPELINE_ID/context/00_requirements.md` (Phase 0)
|
|
322
|
+
- `pipelines/$PIPELINE_ID/context/01_plan.md` (Phase 1)
|
|
323
|
+
- `pipelines/$PIPELINE_ID/context/02_design_spec.md` (Phase 2)
|
|
324
|
+
- `pipelines/$PIPELINE_ID/context/03_api_spec.md` (Phase 2)
|
|
325
|
+
- 등등...
|
|
326
|
+
|
|
327
|
+
### 시그널 프로토콜
|
|
328
|
+
|
|
329
|
+
시그널 파일은 단순 텍스트 파일이며, 대시보드의 Runner가 감지하여 실시간 상태를 업데이트한다.
|
|
310
330
|
|
|
311
331
|
### 시그널 디렉토리
|
|
312
332
|
|