@tienne/gestalt 0.5.0 → 0.6.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.backup.md +442 -0
- package/README.ko.md +466 -0
- package/README.md +315 -283
- package/dist/bin/gestalt.js +8 -0
- package/dist/bin/gestalt.js.map +1 -1
- package/dist/package.json +9 -3
- package/dist/review-agents/performance-reviewer/AGENT.md +31 -0
- package/dist/review-agents/quality-reviewer/AGENT.md +31 -0
- package/dist/review-agents/security-reviewer/AGENT.md +32 -0
- package/dist/role-agents/architect/AGENT.md +30 -0
- package/dist/role-agents/backend-developer/AGENT.md +30 -0
- package/dist/role-agents/designer/AGENT.md +30 -0
- package/dist/role-agents/devops-engineer/AGENT.md +30 -0
- package/dist/role-agents/frontend-developer/AGENT.md +30 -0
- package/dist/role-agents/product-planner/AGENT.md +30 -0
- package/dist/role-agents/qa-engineer/AGENT.md +30 -0
- package/dist/role-agents/researcher/AGENT.md +30 -0
- package/dist/role-agents/technical-writer/AGENT.md +212 -0
- package/dist/skills/agent/SKILL.md +102 -0
- package/dist/skills/execute/SKILL.md +274 -6
- package/dist/src/agent/role-agent-registry.d.ts +4 -2
- package/dist/src/agent/role-agent-registry.d.ts.map +1 -1
- package/dist/src/agent/role-agent-registry.js +12 -3
- package/dist/src/agent/role-agent-registry.js.map +1 -1
- package/dist/src/cli/commands/interview.d.ts +4 -1
- package/dist/src/cli/commands/interview.d.ts.map +1 -1
- package/dist/src/cli/commands/interview.js +55 -2
- package/dist/src/cli/commands/interview.js.map +1 -1
- package/dist/src/cli/index.d.ts.map +1 -1
- package/dist/src/cli/index.js +3 -2
- package/dist/src/cli/index.js.map +1 -1
- package/dist/src/core/config.d.ts +3 -0
- package/dist/src/core/config.d.ts.map +1 -1
- package/dist/src/core/config.js +4 -0
- package/dist/src/core/config.js.map +1 -1
- package/dist/src/core/types.d.ts +28 -0
- package/dist/src/core/types.d.ts.map +1 -1
- package/dist/src/mcp/server.d.ts.map +1 -1
- package/dist/src/mcp/server.js +12 -1
- package/dist/src/mcp/server.js.map +1 -1
- package/dist/src/mcp/tools/agent-passthrough.d.ts +7 -0
- package/dist/src/mcp/tools/agent-passthrough.d.ts.map +1 -0
- package/dist/src/mcp/tools/agent-passthrough.js +49 -0
- package/dist/src/mcp/tools/agent-passthrough.js.map +1 -0
- package/dist/src/recording/filename-generator.d.ts +18 -0
- package/dist/src/recording/filename-generator.d.ts.map +1 -0
- package/dist/src/recording/filename-generator.js +60 -0
- package/dist/src/recording/filename-generator.js.map +1 -0
- package/dist/src/recording/gif-generator.d.ts +21 -0
- package/dist/src/recording/gif-generator.d.ts.map +1 -0
- package/dist/src/recording/gif-generator.js +121 -0
- package/dist/src/recording/gif-generator.js.map +1 -0
- package/dist/src/recording/recording-dir.d.ts +5 -0
- package/dist/src/recording/recording-dir.d.ts.map +1 -0
- package/dist/src/recording/recording-dir.js +13 -0
- package/dist/src/recording/recording-dir.js.map +1 -0
- package/dist/src/recording/resume-detector.d.ts +10 -0
- package/dist/src/recording/resume-detector.d.ts.map +1 -0
- package/dist/src/recording/resume-detector.js +14 -0
- package/dist/src/recording/resume-detector.js.map +1 -0
- package/dist/src/recording/segment-merger.d.ts +27 -0
- package/dist/src/recording/segment-merger.d.ts.map +1 -0
- package/dist/src/recording/segment-merger.js +65 -0
- package/dist/src/recording/segment-merger.js.map +1 -0
- package/dist/src/recording/terminal-recorder.d.ts +31 -0
- package/dist/src/recording/terminal-recorder.d.ts.map +1 -0
- package/dist/src/recording/terminal-recorder.js +111 -0
- package/dist/src/recording/terminal-recorder.js.map +1 -0
- package/package.json +9 -3
- package/review-agents/performance-reviewer/AGENT.md +31 -0
- package/review-agents/quality-reviewer/AGENT.md +31 -0
- package/review-agents/security-reviewer/AGENT.md +32 -0
- package/role-agents/architect/AGENT.md +30 -0
- package/role-agents/backend-developer/AGENT.md +30 -0
- package/role-agents/designer/AGENT.md +30 -0
- package/role-agents/devops-engineer/AGENT.md +30 -0
- package/role-agents/frontend-developer/AGENT.md +30 -0
- package/role-agents/product-planner/AGENT.md +30 -0
- package/role-agents/qa-engineer/AGENT.md +30 -0
- package/role-agents/researcher/AGENT.md +30 -0
- package/role-agents/technical-writer/AGENT.md +212 -0
- package/skills/agent/SKILL.md +102 -0
- package/skills/execute/SKILL.md +274 -6
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export declare const RECORDINGS_BASE_DIR = ".gestalt/recordings";
|
|
2
|
+
/** sessionId에 대한 .frames 파일 경로를 반환하고, 부모 디렉토리가 없으면 생성한다 */
|
|
3
|
+
export declare function ensureRecordingsDir(): void;
|
|
4
|
+
export declare function getFramesPath(sessionId: string): string;
|
|
5
|
+
//# sourceMappingURL=recording-dir.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recording-dir.d.ts","sourceRoot":"","sources":["../../../src/recording/recording-dir.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,mBAAmB,wBAAwB,CAAC;AAEzD,2DAA2D;AAC3D,wBAAgB,mBAAmB,IAAI,IAAI,CAI1C;AAED,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAEvD"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { mkdirSync, existsSync } from 'node:fs';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
export const RECORDINGS_BASE_DIR = '.gestalt/recordings';
|
|
4
|
+
/** sessionId에 대한 .frames 파일 경로를 반환하고, 부모 디렉토리가 없으면 생성한다 */
|
|
5
|
+
export function ensureRecordingsDir() {
|
|
6
|
+
if (!existsSync(RECORDINGS_BASE_DIR)) {
|
|
7
|
+
mkdirSync(RECORDINGS_BASE_DIR, { recursive: true });
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
export function getFramesPath(sessionId) {
|
|
11
|
+
return join(RECORDINGS_BASE_DIR, `${sessionId}.frames`);
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=recording-dir.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recording-dir.js","sourceRoot":"","sources":["../../../src/recording/recording-dir.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAChD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,MAAM,CAAC,MAAM,mBAAmB,GAAG,qBAAqB,CAAC;AAEzD,2DAA2D;AAC3D,MAAM,UAAU,mBAAmB;IACjC,IAAI,CAAC,UAAU,CAAC,mBAAmB,CAAC,EAAE,CAAC;QACrC,SAAS,CAAC,mBAAmB,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACtD,CAAC;AACH,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,SAAiB;IAC7C,OAAO,IAAI,CAAC,mBAAmB,EAAE,GAAG,SAAS,SAAS,CAAC,CAAC;AAC1D,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export interface ResumeInfo {
|
|
2
|
+
isResuming: boolean;
|
|
3
|
+
framesPath: string;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* sessionId에 해당하는 .frames 임시 파일이 존재하는지 확인한다.
|
|
7
|
+
* 존재하면 이전 녹화를 이어붙일 수 있음을 의미한다.
|
|
8
|
+
*/
|
|
9
|
+
export declare function detectResume(sessionId: string): ResumeInfo;
|
|
10
|
+
//# sourceMappingURL=resume-detector.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resume-detector.d.ts","sourceRoot":"","sources":["../../../src/recording/resume-detector.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,UAAU;IACzB,UAAU,EAAE,OAAO,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,UAAU,CAM1D"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { existsSync } from 'node:fs';
|
|
2
|
+
import { getFramesPath } from './recording-dir.js';
|
|
3
|
+
/**
|
|
4
|
+
* sessionId에 해당하는 .frames 임시 파일이 존재하는지 확인한다.
|
|
5
|
+
* 존재하면 이전 녹화를 이어붙일 수 있음을 의미한다.
|
|
6
|
+
*/
|
|
7
|
+
export function detectResume(sessionId) {
|
|
8
|
+
const framesPath = getFramesPath(sessionId);
|
|
9
|
+
return {
|
|
10
|
+
isResuming: existsSync(framesPath),
|
|
11
|
+
framesPath,
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=resume-detector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resume-detector.js","sourceRoot":"","sources":["../../../src/recording/resume-detector.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAOnD;;;GAGG;AACH,MAAM,UAAU,YAAY,CAAC,SAAiB;IAC5C,MAAM,UAAU,GAAG,aAAa,CAAC,SAAS,CAAC,CAAC;IAC5C,OAAO;QACL,UAAU,EAAE,UAAU,CAAC,UAAU,CAAC;QAClC,UAAU;KACX,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { TerminalFrame } from '../core/types.js';
|
|
2
|
+
import { GifGenerator } from './gif-generator.js';
|
|
3
|
+
/**
|
|
4
|
+
* SegmentMerger: 동일 sessionId의 여러 .frames 파일 세그먼트를
|
|
5
|
+
* 시간순으로 병합해 GifGenerator에 전달한다.
|
|
6
|
+
*
|
|
7
|
+
* 현재 아키텍처에서는 sessionId당 .frames 파일이 1개이므로,
|
|
8
|
+
* 단일 파일 읽기도 이 클래스를 경유해 일관된 인터페이스를 유지한다.
|
|
9
|
+
*/
|
|
10
|
+
export declare class SegmentMerger {
|
|
11
|
+
private readonly gifGenerator;
|
|
12
|
+
constructor(gifGenerator?: GifGenerator);
|
|
13
|
+
/**
|
|
14
|
+
* 여러 .frames 파일을 읽어 타임스탬프 기준 오름차순으로 병합한다.
|
|
15
|
+
* 각 세그먼트 사이의 긴 갭(5초 이상)은 3초로 압축한다.
|
|
16
|
+
*/
|
|
17
|
+
mergeFrameFiles(framesPaths: string[]): Promise<TerminalFrame[]>;
|
|
18
|
+
/**
|
|
19
|
+
* 단일 .frames 파일 읽기 (공통 인터페이스 유지)
|
|
20
|
+
*/
|
|
21
|
+
readSingleFile(framesPath: string): Promise<TerminalFrame[]>;
|
|
22
|
+
/**
|
|
23
|
+
* 타임스탬프를 오름차순 정렬하고 큰 갭을 압축한다.
|
|
24
|
+
*/
|
|
25
|
+
private normalizeTimestamps;
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=segment-merger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"segment-merger.d.ts","sourceRoot":"","sources":["../../../src/recording/segment-merger.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAElD;;;;;;GAMG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAe;gBAEhC,YAAY,CAAC,EAAE,YAAY;IAIvC;;;OAGG;IACG,eAAe,CAAC,WAAW,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC;IAYtE;;OAEG;IACG,cAAc,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC;IAIlE;;OAEG;IACH,OAAO,CAAC,mBAAmB;CA4B5B"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { existsSync } from 'node:fs';
|
|
2
|
+
import { GifGenerator } from './gif-generator.js';
|
|
3
|
+
/**
|
|
4
|
+
* SegmentMerger: 동일 sessionId의 여러 .frames 파일 세그먼트를
|
|
5
|
+
* 시간순으로 병합해 GifGenerator에 전달한다.
|
|
6
|
+
*
|
|
7
|
+
* 현재 아키텍처에서는 sessionId당 .frames 파일이 1개이므로,
|
|
8
|
+
* 단일 파일 읽기도 이 클래스를 경유해 일관된 인터페이스를 유지한다.
|
|
9
|
+
*/
|
|
10
|
+
export class SegmentMerger {
|
|
11
|
+
gifGenerator;
|
|
12
|
+
constructor(gifGenerator) {
|
|
13
|
+
this.gifGenerator = gifGenerator ?? new GifGenerator();
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* 여러 .frames 파일을 읽어 타임스탬프 기준 오름차순으로 병합한다.
|
|
17
|
+
* 각 세그먼트 사이의 긴 갭(5초 이상)은 3초로 압축한다.
|
|
18
|
+
*/
|
|
19
|
+
async mergeFrameFiles(framesPaths) {
|
|
20
|
+
const allFrames = [];
|
|
21
|
+
for (const framesPath of framesPaths) {
|
|
22
|
+
if (!existsSync(framesPath))
|
|
23
|
+
continue;
|
|
24
|
+
const frames = await this.gifGenerator.readFrames(framesPath);
|
|
25
|
+
allFrames.push(...frames);
|
|
26
|
+
}
|
|
27
|
+
return this.normalizeTimestamps(allFrames);
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* 단일 .frames 파일 읽기 (공통 인터페이스 유지)
|
|
31
|
+
*/
|
|
32
|
+
async readSingleFile(framesPath) {
|
|
33
|
+
return this.mergeFrameFiles([framesPath]);
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* 타임스탬프를 오름차순 정렬하고 큰 갭을 압축한다.
|
|
37
|
+
*/
|
|
38
|
+
normalizeTimestamps(frames) {
|
|
39
|
+
if (frames.length === 0)
|
|
40
|
+
return [];
|
|
41
|
+
// 타임스탬프 오름차순 정렬
|
|
42
|
+
frames.sort((a, b) => a.timestamp - b.timestamp);
|
|
43
|
+
// 세그먼트 갭 압축: 5초 이상 빈 구간은 3초로 압축
|
|
44
|
+
const GAP_THRESHOLD_MS = 5000;
|
|
45
|
+
const MAX_GAP_MS = 3000;
|
|
46
|
+
const normalized = [frames[0]];
|
|
47
|
+
for (let i = 1; i < frames.length; i++) {
|
|
48
|
+
const curr = frames[i];
|
|
49
|
+
const prev_frame = frames[i - 1];
|
|
50
|
+
const gap = curr.timestamp - prev_frame.timestamp;
|
|
51
|
+
if (gap > GAP_THRESHOLD_MS) {
|
|
52
|
+
const prev = normalized[normalized.length - 1];
|
|
53
|
+
normalized.push({
|
|
54
|
+
...curr,
|
|
55
|
+
timestamp: prev.timestamp + MAX_GAP_MS,
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
normalized.push(curr);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return normalized;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=segment-merger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"segment-merger.js","sourceRoot":"","sources":["../../../src/recording/segment-merger.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAErC,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAElD;;;;;;GAMG;AACH,MAAM,OAAO,aAAa;IACP,YAAY,CAAe;IAE5C,YAAY,YAA2B;QACrC,IAAI,CAAC,YAAY,GAAG,YAAY,IAAI,IAAI,YAAY,EAAE,CAAC;IACzD,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,eAAe,CAAC,WAAqB;QACzC,MAAM,SAAS,GAAoB,EAAE,CAAC;QAEtC,KAAK,MAAM,UAAU,IAAI,WAAW,EAAE,CAAC;YACrC,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC;gBAAE,SAAS;YACtC,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC;YAC9D,SAAS,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,CAAC;QAC5B,CAAC;QAED,OAAO,IAAI,CAAC,mBAAmB,CAAC,SAAS,CAAC,CAAC;IAC7C,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,cAAc,CAAC,UAAkB;QACrC,OAAO,IAAI,CAAC,eAAe,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC;IAC5C,CAAC;IAED;;OAEG;IACK,mBAAmB,CAAC,MAAuB;QACjD,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,EAAE,CAAC;QAEnC,gBAAgB;QAChB,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,GAAG,CAAC,CAAC,SAAS,CAAC,CAAC;QAEjD,gCAAgC;QAChC,MAAM,gBAAgB,GAAG,IAAI,CAAC;QAC9B,MAAM,UAAU,GAAG,IAAI,CAAC;QAExB,MAAM,UAAU,GAAoB,CAAC,MAAM,CAAC,CAAC,CAAE,CAAC,CAAC;QACjD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACvC,MAAM,IAAI,GAAG,MAAM,CAAC,CAAC,CAAE,CAAC;YACxB,MAAM,UAAU,GAAG,MAAM,CAAC,CAAC,GAAG,CAAC,CAAE,CAAC;YAClC,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,GAAG,UAAU,CAAC,SAAS,CAAC;YAClD,IAAI,GAAG,GAAG,gBAAgB,EAAE,CAAC;gBAC3B,MAAM,IAAI,GAAG,UAAU,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,CAAE,CAAC;gBAChD,UAAU,CAAC,IAAI,CAAC;oBACd,GAAG,IAAI;oBACP,SAAS,EAAE,IAAI,CAAC,SAAS,GAAG,UAAU;iBACvC,CAAC,CAAC;YACL,CAAC;iBAAM,CAAC;gBACN,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACxB,CAAC;QACH,CAAC;QAED,OAAO,UAAU,CAAC;IACpB,CAAC;CACF"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { RecordingSegment } from '../core/types.js';
|
|
2
|
+
/**
|
|
3
|
+
* TerminalRecorder: process.stdout.write를 인터셉트하여
|
|
4
|
+
* TerminalFrame을 .frames NDJSON 파일에 실시간 append한다.
|
|
5
|
+
*
|
|
6
|
+
* node-pty 없이도 동작하지만, PTY 기반 캡처가 필요한 경우
|
|
7
|
+
* 향후 node-pty 통합으로 확장 가능하도록 설계한다.
|
|
8
|
+
*/
|
|
9
|
+
export declare class TerminalRecorder {
|
|
10
|
+
private readonly sessionId;
|
|
11
|
+
private readonly framesPath;
|
|
12
|
+
private segment;
|
|
13
|
+
private isRecording;
|
|
14
|
+
private frameBuffer;
|
|
15
|
+
private originalStdoutWrite;
|
|
16
|
+
constructor(sessionId: string);
|
|
17
|
+
/** 녹화 시작. 기존 .frames 파일이 있으면 이어서 append (resume) */
|
|
18
|
+
start(): RecordingSegment;
|
|
19
|
+
/** 녹화 일시 중지 (세션 중단 시) */
|
|
20
|
+
pause(): void;
|
|
21
|
+
/** 녹화 완전 종료 */
|
|
22
|
+
stop(): RecordingSegment | null;
|
|
23
|
+
get recording(): boolean;
|
|
24
|
+
get framesFilePath(): string;
|
|
25
|
+
/** stdout.write 인터셉트 */
|
|
26
|
+
private interceptStdout;
|
|
27
|
+
private restoreStdout;
|
|
28
|
+
private captureFrame;
|
|
29
|
+
private flushBuffer;
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=terminal-recorder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"terminal-recorder.d.ts","sourceRoot":"","sources":["../../../src/recording/terminal-recorder.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAiB,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAExE;;;;;;GAMG;AACH,qBAAa,gBAAgB;IASf,OAAO,CAAC,QAAQ,CAAC,SAAS;IARtC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,OAAO,CAAiC;IAChD,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,WAAW,CAAuB;IAG1C,OAAO,CAAC,mBAAmB,CAA+B;gBAE7B,SAAS,EAAE,MAAM;IAK9C,oDAAoD;IACpD,KAAK,IAAI,gBAAgB;IAoBzB,yBAAyB;IACzB,KAAK,IAAI,IAAI;IAUb,eAAe;IACf,IAAI,IAAI,gBAAgB,GAAG,IAAI;IAO/B,IAAI,SAAS,IAAI,OAAO,CAEvB;IAED,IAAI,cAAc,IAAI,MAAM,CAE3B;IAED,wBAAwB;IACxB,OAAO,CAAC,eAAe;IA2BvB,OAAO,CAAC,aAAa;IAMrB,OAAO,CAAC,YAAY;IAkBpB,OAAO,CAAC,WAAW;CAMpB"}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { appendFileSync, existsSync } from 'node:fs';
|
|
2
|
+
import { ensureRecordingsDir, getFramesPath } from './recording-dir.js';
|
|
3
|
+
/**
|
|
4
|
+
* TerminalRecorder: process.stdout.write를 인터셉트하여
|
|
5
|
+
* TerminalFrame을 .frames NDJSON 파일에 실시간 append한다.
|
|
6
|
+
*
|
|
7
|
+
* node-pty 없이도 동작하지만, PTY 기반 캡처가 필요한 경우
|
|
8
|
+
* 향후 node-pty 통합으로 확장 가능하도록 설계한다.
|
|
9
|
+
*/
|
|
10
|
+
export class TerminalRecorder {
|
|
11
|
+
sessionId;
|
|
12
|
+
framesPath;
|
|
13
|
+
segment = null;
|
|
14
|
+
isRecording = false;
|
|
15
|
+
frameBuffer = [];
|
|
16
|
+
// 원본 stdout.write 저장
|
|
17
|
+
originalStdoutWrite;
|
|
18
|
+
constructor(sessionId) {
|
|
19
|
+
this.sessionId = sessionId;
|
|
20
|
+
ensureRecordingsDir();
|
|
21
|
+
this.framesPath = getFramesPath(sessionId);
|
|
22
|
+
}
|
|
23
|
+
/** 녹화 시작. 기존 .frames 파일이 있으면 이어서 append (resume) */
|
|
24
|
+
start() {
|
|
25
|
+
if (this.isRecording)
|
|
26
|
+
return this.segment;
|
|
27
|
+
const isResuming = existsSync(this.framesPath);
|
|
28
|
+
this.segment = {
|
|
29
|
+
sessionId: this.sessionId,
|
|
30
|
+
framesPath: this.framesPath,
|
|
31
|
+
startedAt: Date.now(),
|
|
32
|
+
};
|
|
33
|
+
this.isRecording = true;
|
|
34
|
+
this.interceptStdout();
|
|
35
|
+
if (!isResuming) {
|
|
36
|
+
// 새 녹화: 빈 파일로 시작
|
|
37
|
+
}
|
|
38
|
+
return this.segment;
|
|
39
|
+
}
|
|
40
|
+
/** 녹화 일시 중지 (세션 중단 시) */
|
|
41
|
+
pause() {
|
|
42
|
+
if (!this.isRecording)
|
|
43
|
+
return;
|
|
44
|
+
this.restoreStdout();
|
|
45
|
+
this.flushBuffer();
|
|
46
|
+
if (this.segment) {
|
|
47
|
+
this.segment.endedAt = Date.now();
|
|
48
|
+
}
|
|
49
|
+
this.isRecording = false;
|
|
50
|
+
}
|
|
51
|
+
/** 녹화 완전 종료 */
|
|
52
|
+
stop() {
|
|
53
|
+
if (this.isRecording) {
|
|
54
|
+
this.pause();
|
|
55
|
+
}
|
|
56
|
+
return this.segment;
|
|
57
|
+
}
|
|
58
|
+
get recording() {
|
|
59
|
+
return this.isRecording;
|
|
60
|
+
}
|
|
61
|
+
get framesFilePath() {
|
|
62
|
+
return this.framesPath;
|
|
63
|
+
}
|
|
64
|
+
/** stdout.write 인터셉트 */
|
|
65
|
+
interceptStdout() {
|
|
66
|
+
const self = this;
|
|
67
|
+
this.originalStdoutWrite = process.stdout.write.bind(process.stdout);
|
|
68
|
+
// overwrite with interceptor
|
|
69
|
+
const intercepted = function (chunk, encodingOrCallback, callback) {
|
|
70
|
+
const data = typeof chunk === 'string' ? chunk : Buffer.from(chunk).toString('utf8');
|
|
71
|
+
self.captureFrame(data);
|
|
72
|
+
// 원본 write 호출
|
|
73
|
+
if (typeof encodingOrCallback === 'function') {
|
|
74
|
+
return self.originalStdoutWrite(chunk, encodingOrCallback);
|
|
75
|
+
}
|
|
76
|
+
if (typeof encodingOrCallback === 'string') {
|
|
77
|
+
return self.originalStdoutWrite(chunk, encodingOrCallback, callback);
|
|
78
|
+
}
|
|
79
|
+
return self.originalStdoutWrite(chunk);
|
|
80
|
+
};
|
|
81
|
+
process.stdout.write = intercepted;
|
|
82
|
+
}
|
|
83
|
+
restoreStdout() {
|
|
84
|
+
if (this.originalStdoutWrite) {
|
|
85
|
+
process.stdout.write = this.originalStdoutWrite;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
captureFrame(data) {
|
|
89
|
+
if (!data || !this.isRecording)
|
|
90
|
+
return;
|
|
91
|
+
const frame = {
|
|
92
|
+
timestamp: Date.now(),
|
|
93
|
+
data,
|
|
94
|
+
cols: process.stdout.columns ?? 80,
|
|
95
|
+
rows: process.stdout.rows ?? 24,
|
|
96
|
+
};
|
|
97
|
+
this.frameBuffer.push(frame);
|
|
98
|
+
// 버퍼가 10개 이상 쌓이면 즉시 flush
|
|
99
|
+
if (this.frameBuffer.length >= 10) {
|
|
100
|
+
this.flushBuffer();
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
flushBuffer() {
|
|
104
|
+
if (this.frameBuffer.length === 0)
|
|
105
|
+
return;
|
|
106
|
+
const lines = this.frameBuffer.map((f) => JSON.stringify(f)).join('\n') + '\n';
|
|
107
|
+
appendFileSync(this.framesPath, lines, 'utf8');
|
|
108
|
+
this.frameBuffer = [];
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
//# sourceMappingURL=terminal-recorder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"terminal-recorder.js","sourceRoot":"","sources":["../../../src/recording/terminal-recorder.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tienne/gestalt",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "TypeScript AI Development Harness - Gestalt psychology-driven requirement clarification",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/src/index.js",
|
|
@@ -14,6 +14,8 @@
|
|
|
14
14
|
"files": [
|
|
15
15
|
"dist",
|
|
16
16
|
"agents",
|
|
17
|
+
"role-agents",
|
|
18
|
+
"review-agents",
|
|
17
19
|
"skills",
|
|
18
20
|
"schemas",
|
|
19
21
|
"CLAUDE.md"
|
|
@@ -21,7 +23,7 @@
|
|
|
21
23
|
"scripts": {
|
|
22
24
|
"dev": "tsx bin/gestalt.ts",
|
|
23
25
|
"build": "tsc",
|
|
24
|
-
"postbuild": "cp -r agents dist/ && cp -r skills dist/ && cp -r schemas dist/ && cp package.json dist/ && chmod +x dist/bin/gestalt.js",
|
|
26
|
+
"postbuild": "cp -r agents dist/ && cp -r role-agents dist/ && cp -r review-agents dist/ && cp -r skills dist/ && cp -r schemas dist/ && cp package.json dist/ && chmod +x dist/bin/gestalt.js",
|
|
25
27
|
"prepublishOnly": "pnpm build",
|
|
26
28
|
"test": "vitest run",
|
|
27
29
|
"test:watch": "vitest",
|
|
@@ -39,8 +41,11 @@
|
|
|
39
41
|
"chokidar": "^4.0.3",
|
|
40
42
|
"commander": "^13.1.0",
|
|
41
43
|
"dotenv": "^17.3.1",
|
|
44
|
+
"gifencoder": "^2.0.1",
|
|
42
45
|
"gray-matter": "^4.0.3",
|
|
43
46
|
"ink": "^6.8.0",
|
|
47
|
+
"jimp": "^1.6.0",
|
|
48
|
+
"node-pty": "^1.1.0",
|
|
44
49
|
"openai": "^6.27.0",
|
|
45
50
|
"react": "^19.2.4",
|
|
46
51
|
"zod": "^3.24.2"
|
|
@@ -55,7 +60,8 @@
|
|
|
55
60
|
"pnpm": {
|
|
56
61
|
"onlyBuiltDependencies": [
|
|
57
62
|
"better-sqlite3",
|
|
58
|
-
"esbuild"
|
|
63
|
+
"esbuild",
|
|
64
|
+
"node-pty"
|
|
59
65
|
]
|
|
60
66
|
}
|
|
61
67
|
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: performance-reviewer
|
|
3
|
+
tier: standard
|
|
4
|
+
pipeline: review
|
|
5
|
+
role: true
|
|
6
|
+
domain: ["performance", "optimization", "memory", "cpu", "latency", "caching", "lazy-loading", "bundle-size", "rendering", "database", "query", "n+1", "async"]
|
|
7
|
+
description: "성능 리뷰 전문가. 메모리 누수, N+1 쿼리, 불필요한 재렌더링, 번들 사이즈, 비동기 처리 등 성능 관점의 코드리뷰를 수행한다."
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
You are the Performance Reviewer agent.
|
|
11
|
+
|
|
12
|
+
Your expertise covers runtime performance, memory management, and optimization strategies.
|
|
13
|
+
|
|
14
|
+
## Review Focus
|
|
15
|
+
|
|
16
|
+
When reviewing code, check for:
|
|
17
|
+
|
|
18
|
+
1. **Memory Leaks**: Uncleaned event listeners, timers, subscriptions
|
|
19
|
+
2. **Unnecessary Computation**: Redundant loops, missing memoization, expensive operations in hot paths
|
|
20
|
+
3. **Database/API**: N+1 queries, missing pagination, unindexed lookups
|
|
21
|
+
4. **Async Patterns**: Unhandled promises, sequential awaits that could be parallel, missing error boundaries
|
|
22
|
+
5. **Bundle/Load**: Large imports that could be lazy-loaded, unused dependencies
|
|
23
|
+
|
|
24
|
+
## Output Format
|
|
25
|
+
|
|
26
|
+
For each issue found, provide:
|
|
27
|
+
- severity: critical | high | warning
|
|
28
|
+
- category: "performance"
|
|
29
|
+
- file and line number
|
|
30
|
+
- Clear description of the performance impact
|
|
31
|
+
- Specific optimization suggestion
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: quality-reviewer
|
|
3
|
+
tier: standard
|
|
4
|
+
pipeline: review
|
|
5
|
+
role: true
|
|
6
|
+
domain: ["code-quality", "readability", "maintainability", "solid", "dry", "naming", "complexity", "error-handling", "testing", "documentation", "refactoring", "design-pattern"]
|
|
7
|
+
description: "코드 품질 리뷰 전문가. 가독성, 유지보수성, SOLID 원칙, 에러 핸들링, 중복 코드, 네이밍 컨벤션 등 코드 품질 관점의 리뷰를 수행한다."
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
You are the Quality Reviewer agent.
|
|
11
|
+
|
|
12
|
+
Your expertise covers code quality, design patterns, and maintainability.
|
|
13
|
+
|
|
14
|
+
## Review Focus
|
|
15
|
+
|
|
16
|
+
When reviewing code, check for:
|
|
17
|
+
|
|
18
|
+
1. **Readability**: Unclear naming, overly complex logic, missing context
|
|
19
|
+
2. **Maintainability**: Tight coupling, god objects, missing abstractions
|
|
20
|
+
3. **Error Handling**: Swallowed errors, missing error boundaries, unclear error messages
|
|
21
|
+
4. **DRY Violations**: Duplicated logic that should be extracted
|
|
22
|
+
5. **Complexity**: Functions doing too many things, deep nesting, high cyclomatic complexity
|
|
23
|
+
|
|
24
|
+
## Output Format
|
|
25
|
+
|
|
26
|
+
For each issue found, provide:
|
|
27
|
+
- severity: critical | high | warning
|
|
28
|
+
- category: "quality"
|
|
29
|
+
- file and line number
|
|
30
|
+
- Clear description of the quality concern
|
|
31
|
+
- Specific refactoring suggestion
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: security-reviewer
|
|
3
|
+
tier: standard
|
|
4
|
+
pipeline: review
|
|
5
|
+
role: true
|
|
6
|
+
domain: ["security", "authentication", "authorization", "injection", "xss", "csrf", "encryption", "secrets", "vulnerability", "owasp", "sanitization", "validation"]
|
|
7
|
+
description: "보안 리뷰 전문가. SQL injection, XSS, CSRF, 인증/인가 취약점, 시크릿 노출, 입력 검증 등 보안 관점의 코드리뷰를 수행한다."
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
You are the Security Reviewer agent.
|
|
11
|
+
|
|
12
|
+
Your expertise covers application security, vulnerability detection, and secure coding practices.
|
|
13
|
+
|
|
14
|
+
## Review Focus
|
|
15
|
+
|
|
16
|
+
When reviewing code, check for:
|
|
17
|
+
|
|
18
|
+
1. **Injection Attacks**: SQL injection, command injection, path traversal
|
|
19
|
+
2. **Cross-Site Scripting (XSS)**: Unsanitized user input in HTML/JS output
|
|
20
|
+
3. **Authentication/Authorization**: Missing auth checks, improper session handling, privilege escalation
|
|
21
|
+
4. **Secrets Exposure**: Hardcoded API keys, tokens, passwords in source code
|
|
22
|
+
5. **Input Validation**: Missing or insufficient validation at system boundaries
|
|
23
|
+
6. **Dependency Security**: Known vulnerabilities in imported packages
|
|
24
|
+
|
|
25
|
+
## Output Format
|
|
26
|
+
|
|
27
|
+
For each issue found, provide:
|
|
28
|
+
- severity: critical | high | warning
|
|
29
|
+
- category: "security"
|
|
30
|
+
- file and line number
|
|
31
|
+
- Clear description of the vulnerability
|
|
32
|
+
- Specific fix suggestion with code example
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: architect
|
|
3
|
+
tier: frontier
|
|
4
|
+
pipeline: execute
|
|
5
|
+
role: true
|
|
6
|
+
domain: ["architecture", "design-pattern", "system-design", "scalability", "modularity", "abstraction", "dependency", "interface", "coupling", "cohesion", "solid", "ddd"]
|
|
7
|
+
description: "소프트웨어 아키텍트 전문가. 시스템 설계, 모듈 구조, 의존성 관리, 확장성 관점을 제공한다."
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
You are the Software Architect role agent.
|
|
11
|
+
|
|
12
|
+
Your expertise covers system design, module structure, dependency management, and scalability patterns.
|
|
13
|
+
|
|
14
|
+
## Perspective Focus
|
|
15
|
+
|
|
16
|
+
When reviewing a task, provide guidance on:
|
|
17
|
+
|
|
18
|
+
1. **System Design**: How the change fits into the overall architecture, module boundaries
|
|
19
|
+
2. **Dependencies**: Coupling analysis, dependency direction, interface contracts
|
|
20
|
+
3. **Patterns**: Appropriate design patterns, anti-patterns to avoid
|
|
21
|
+
4. **Scalability**: How the design handles growth, potential bottlenecks
|
|
22
|
+
5. **Maintainability**: Code organization, separation of concerns, future extensibility
|
|
23
|
+
|
|
24
|
+
## Output Format
|
|
25
|
+
|
|
26
|
+
Provide a structured perspective with:
|
|
27
|
+
- Architectural impact analysis
|
|
28
|
+
- Module boundary recommendations
|
|
29
|
+
- Dependency graph changes
|
|
30
|
+
- Long-term maintainability considerations
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: backend-developer
|
|
3
|
+
tier: standard
|
|
4
|
+
pipeline: execute
|
|
5
|
+
role: true
|
|
6
|
+
domain: ["api", "database", "server", "rest", "graphql", "authentication", "authorization", "middleware", "orm", "sql", "nosql", "caching", "queue", "backend", "microservice"]
|
|
7
|
+
description: "백엔드 개발 전문가. API 설계, 데이터베이스 모델링, 인증/인가, 서버 아키텍처 관점을 제공한다."
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
You are the Backend Developer role agent.
|
|
11
|
+
|
|
12
|
+
Your expertise covers API design, database modeling, server architecture, and data processing.
|
|
13
|
+
|
|
14
|
+
## Perspective Focus
|
|
15
|
+
|
|
16
|
+
When reviewing a task, provide guidance on:
|
|
17
|
+
|
|
18
|
+
1. **API Design**: RESTful conventions, error responses, pagination, versioning
|
|
19
|
+
2. **Data Modeling**: Schema design, relationships, indexing strategies, migrations
|
|
20
|
+
3. **Security**: Input validation, authentication flows, authorization patterns
|
|
21
|
+
4. **Performance**: Query optimization, caching strategies, connection pooling
|
|
22
|
+
5. **Reliability**: Error handling, retry logic, idempotency, transaction management
|
|
23
|
+
|
|
24
|
+
## Output Format
|
|
25
|
+
|
|
26
|
+
Provide a structured perspective with:
|
|
27
|
+
- API contract recommendations
|
|
28
|
+
- Data model considerations
|
|
29
|
+
- Security implications
|
|
30
|
+
- Performance and scalability notes
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: designer
|
|
3
|
+
tier: standard
|
|
4
|
+
pipeline: execute
|
|
5
|
+
role: true
|
|
6
|
+
domain: ["design", "ui", "ux", "figma", "prototype", "wireframe", "design-system", "color", "typography", "spacing", "animation", "interaction", "visual"]
|
|
7
|
+
description: "디자인 전문가. 사용자 경험, 시각 디자인, 인터랙션 디자인, 디자인 시스템 관점을 제공한다."
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
You are the Designer role agent.
|
|
11
|
+
|
|
12
|
+
Your expertise covers user experience design, visual design, interaction patterns, and design systems.
|
|
13
|
+
|
|
14
|
+
## Perspective Focus
|
|
15
|
+
|
|
16
|
+
When reviewing a task, provide guidance on:
|
|
17
|
+
|
|
18
|
+
1. **User Flow**: How users navigate through the feature, edge cases in interaction
|
|
19
|
+
2. **Visual Hierarchy**: Layout, typography, color usage, spacing consistency
|
|
20
|
+
3. **Design System**: Reuse of existing components, tokens, and patterns
|
|
21
|
+
4. **Interaction Design**: Micro-interactions, feedback, transitions, affordances
|
|
22
|
+
5. **Inclusive Design**: Color contrast, touch targets, cognitive load reduction
|
|
23
|
+
|
|
24
|
+
## Output Format
|
|
25
|
+
|
|
26
|
+
Provide a structured perspective with:
|
|
27
|
+
- User experience recommendations
|
|
28
|
+
- Visual design guidelines
|
|
29
|
+
- Design system component suggestions
|
|
30
|
+
- Interaction pattern references
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: devops-engineer
|
|
3
|
+
tier: standard
|
|
4
|
+
pipeline: execute
|
|
5
|
+
role: true
|
|
6
|
+
domain: ["deploy", "ci", "cd", "docker", "kubernetes", "infrastructure", "monitoring", "logging", "pipeline", "cloud", "aws", "gcp", "terraform", "devops", "observability"]
|
|
7
|
+
description: "DevOps 엔지니어 전문가. 배포, CI/CD, 인프라, 모니터링, 운영 관점을 제공한다."
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
You are the DevOps Engineer role agent.
|
|
11
|
+
|
|
12
|
+
Your expertise covers deployment, CI/CD, infrastructure, monitoring, and operational concerns.
|
|
13
|
+
|
|
14
|
+
## Perspective Focus
|
|
15
|
+
|
|
16
|
+
When reviewing a task, provide guidance on:
|
|
17
|
+
|
|
18
|
+
1. **Deployment**: How the change affects deployment, rollback strategy, feature flags
|
|
19
|
+
2. **CI/CD**: Pipeline changes needed, build steps, test stages
|
|
20
|
+
3. **Infrastructure**: Resource requirements, scaling considerations, environment config
|
|
21
|
+
4. **Observability**: Logging, metrics, alerting, distributed tracing
|
|
22
|
+
5. **Operational Safety**: Health checks, graceful degradation, runbook updates
|
|
23
|
+
|
|
24
|
+
## Output Format
|
|
25
|
+
|
|
26
|
+
Provide a structured perspective with:
|
|
27
|
+
- Deployment considerations and risks
|
|
28
|
+
- CI/CD pipeline changes needed
|
|
29
|
+
- Monitoring and alerting recommendations
|
|
30
|
+
- Operational runbook updates
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: frontend-developer
|
|
3
|
+
tier: standard
|
|
4
|
+
pipeline: execute
|
|
5
|
+
role: true
|
|
6
|
+
domain: ["ui", "ux", "react", "css", "html", "javascript", "typescript", "component", "layout", "responsive", "accessibility", "browser", "dom", "state-management", "frontend"]
|
|
7
|
+
description: "프론트엔드 개발 전문가. UI/UX 구현, 컴포넌트 설계, 상태 관리, 접근성, 반응형 디자인 관점을 제공한다."
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
You are the Frontend Developer role agent.
|
|
11
|
+
|
|
12
|
+
Your expertise covers UI/UX implementation, component architecture, state management, and browser technologies.
|
|
13
|
+
|
|
14
|
+
## Perspective Focus
|
|
15
|
+
|
|
16
|
+
When reviewing a task, provide guidance on:
|
|
17
|
+
|
|
18
|
+
1. **Component Design**: How to structure UI components for reusability and maintainability
|
|
19
|
+
2. **State Management**: Where state should live, how data flows through the UI
|
|
20
|
+
3. **User Experience**: Loading states, error handling, animations, responsive behavior
|
|
21
|
+
4. **Accessibility**: ARIA attributes, keyboard navigation, screen reader support
|
|
22
|
+
5. **Performance**: Bundle size, rendering optimization, lazy loading strategies
|
|
23
|
+
|
|
24
|
+
## Output Format
|
|
25
|
+
|
|
26
|
+
Provide a structured perspective with:
|
|
27
|
+
- Key implementation decisions and trade-offs
|
|
28
|
+
- Specific code patterns or libraries to use
|
|
29
|
+
- Potential pitfalls to avoid
|
|
30
|
+
- Testing considerations for UI components
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: product-planner
|
|
3
|
+
tier: standard
|
|
4
|
+
pipeline: execute
|
|
5
|
+
role: true
|
|
6
|
+
domain: ["product", "planning", "priority", "user-story", "requirement", "roadmap", "feature", "mvp", "scope", "stakeholder", "acceptance-criteria"]
|
|
7
|
+
description: "프로덕트 기획자 전문가. 태스크 단위 목적, 유저 시나리오, 우선순위, 수용 기준 관점을 제공한다."
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
You are the Product Planner role agent.
|
|
11
|
+
|
|
12
|
+
Your expertise covers product strategy, user scenarios, prioritization, and acceptance criteria.
|
|
13
|
+
|
|
14
|
+
## Perspective Focus
|
|
15
|
+
|
|
16
|
+
When reviewing a task, provide guidance on:
|
|
17
|
+
|
|
18
|
+
1. **Task Purpose**: Why this task matters to the user, business value alignment
|
|
19
|
+
2. **User Scenarios**: Primary and edge user flows, persona considerations
|
|
20
|
+
3. **Priority Assessment**: Must-have vs nice-to-have within this task's scope
|
|
21
|
+
4. **Acceptance Criteria**: Clear, testable success conditions
|
|
22
|
+
5. **Scope Management**: What to include/exclude, MVP boundaries for this task
|
|
23
|
+
|
|
24
|
+
## Output Format
|
|
25
|
+
|
|
26
|
+
Provide a structured perspective with:
|
|
27
|
+
- User scenario descriptions
|
|
28
|
+
- Priority recommendations
|
|
29
|
+
- Acceptance criteria suggestions
|
|
30
|
+
- Scope boundary clarifications
|