@tinygem/soda-agent 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.
@@ -0,0 +1,204 @@
1
+ // 메인 상태 머신 루프: soda의 두뇌
2
+ import { Phase, getErrorMessage } from "./types.js";
3
+ import { cleanupPidFile, createInitialState, ensureSodaIgnored, isCancelled, loadState, readClarifyAnswer, saveState } from "./state.js";
4
+ import { checkCircuitBreaker, CircuitBreakerError } from "./circuit-breaker.js";
5
+ import { executeClaudePhase } from "./executor.js";
6
+ import { buildPhaseConfig, parseGoalConfirmed, resolveNextPhase } from "./phases.js";
7
+ import { getExternalHelp } from "./external-help.js";
8
+ import { logPhaseStart, logPhaseResult, logInfo, logWarn, logError, logSuccess, } from "./logger.js";
9
+ const MAX_CLARIFY_RETRIES = 5; // CLARIFY 최대 재시도 횟수
10
+ const EXTERNAL_HELP_THRESHOLD = 5; // 연속 실패 N회 이상 시 외부 도움 요청
11
+ export async function run(options) {
12
+ const { goal, workingDir, resume, limits, pluginMode, getUserInput } = options;
13
+ // .soda/가 .gitignore에 없으면 추가
14
+ ensureSodaIgnored(workingDir);
15
+ // 상태 로드 또는 생성
16
+ let state;
17
+ if (resume) {
18
+ const loaded = loadState(workingDir);
19
+ if (!loaded) {
20
+ throw new Error("재개할 작업이 없습니다. 새 작업을 시작하세요.");
21
+ }
22
+ state = loaded;
23
+ // CLARIFY 답변 파일 확인 (plugin 모드 resume 시)
24
+ if (state.phase === Phase.CLARIFY) {
25
+ const answer = readClarifyAnswer(workingDir);
26
+ if (answer) {
27
+ if (!state.clarifyMessages)
28
+ state.clarifyMessages = [];
29
+ state.clarifyMessages.push({ role: "user", content: answer });
30
+ saveState(workingDir, state);
31
+ logInfo("CLARIFY 답변을 반영했습니다.");
32
+ }
33
+ }
34
+ logInfo(`이전 작업 재개: ${state.goal} (단계: ${state.phase})`);
35
+ }
36
+ else {
37
+ state = createInitialState(goal);
38
+ }
39
+ // SIGINT/SIGTERM 핸들러 — 상태 저장 + PID 정리
40
+ const cleanup = () => {
41
+ try {
42
+ saveState(workingDir, state);
43
+ }
44
+ catch (e) {
45
+ logWarn(`상태 저장 실패: ${getErrorMessage(e)}`);
46
+ }
47
+ try {
48
+ cleanupPidFile(workingDir);
49
+ }
50
+ catch { /* best-effort */ }
51
+ logInfo("작업 상태가 저장되었습니다. --resume으로 재개할 수 있습니다.");
52
+ };
53
+ const onSigInt = () => { cleanup(); process.exit(130); };
54
+ const onSigTerm = () => { cleanup(); process.exit(143); };
55
+ process.on("SIGINT", onSigInt);
56
+ process.on("SIGTERM", onSigTerm);
57
+ // 메인 루프 — ralph 원칙: 서킷 브레이커/사용자 취소 외에는 절대 멈추지 않는다
58
+ let transientErrors = 0;
59
+ try {
60
+ while (state.phase !== Phase.DONE) {
61
+ // 취소 요청 확인
62
+ if (isCancelled(workingDir)) {
63
+ logInfo("취소 요청이 감지되었습니다. 작업을 중단합니다.");
64
+ saveState(workingDir, state);
65
+ break;
66
+ }
67
+ // 서킷 브레이커 확인
68
+ checkCircuitBreaker(state, limits);
69
+ try {
70
+ state.iterations++;
71
+ logPhaseStart(state.phase, state.iterations);
72
+ // 외부 도움 요청 (연속 5회 이상 실패 시, IMPLEMENT 진입 전)
73
+ let externalAdvice;
74
+ if (state.phase === Phase.IMPLEMENT && state.consecutiveFailures >= EXTERNAL_HELP_THRESHOLD) {
75
+ const help = await getExternalHelp(buildExternalHelpPrompt(state), workingDir);
76
+ if (help) {
77
+ logInfo(`외부 도움 수신 (${help.source})`);
78
+ externalAdvice = help.advice;
79
+ }
80
+ }
81
+ // 단계 실행
82
+ const config = buildPhaseConfig(state, workingDir, externalAdvice);
83
+ // plugin 모드에서는 모든 단계를 비대화형으로 실행 (TTY 없으므로)
84
+ if (pluginMode && !config.skipPermissions) {
85
+ config.skipPermissions = true;
86
+ }
87
+ const result = await executeClaudePhase(config);
88
+ // 결과 처리 — CLARIFY는 goalConfirmed를 1회만 파싱하여 공유
89
+ if (state.phase === Phase.CLARIFY) {
90
+ const goal = parseGoalConfirmed(result.text);
91
+ if (goal) {
92
+ state.goalConfirmed = goal;
93
+ logInfo(`요구사항 확정: ${goal.summary}`);
94
+ logInfo(`태스크: ${goal.tasks.join(", ")}`);
95
+ logInfo(`완성 조건: ${goal.completionCriteria.join(", ")}`);
96
+ }
97
+ else if (getUserInput) {
98
+ // goal_confirmed 없음 → 사용자 입력 수집
99
+ if (!state.clarifyMessages)
100
+ state.clarifyMessages = [];
101
+ state.clarifyMessages.push({ role: "assistant", content: result.text });
102
+ const userAnswer = await getUserInput(result.text, workingDir);
103
+ if (userAnswer === null) {
104
+ // plugin 모드: 질문 저장 후 graceful exit
105
+ saveState(workingDir, state);
106
+ logInfo("사용자 입력 대기 중. --resume으로 재개하세요.");
107
+ return;
108
+ }
109
+ state.clarifyMessages.push({ role: "user", content: userAnswer });
110
+ }
111
+ }
112
+ else {
113
+ handlePhaseResult(state, result.text);
114
+ }
115
+ // 다음 단계 결정
116
+ const transition = resolveNextPhase(state, result.text);
117
+ // CLARIFY 재시도 제한 (state에 영속화하여 --resume 후에도 유지)
118
+ if (state.phase === Phase.CLARIFY && transition.nextPhase === Phase.CLARIFY) {
119
+ state.clarifyRetries = (state.clarifyRetries ?? 0) + 1;
120
+ if (state.clarifyRetries >= MAX_CLARIFY_RETRIES) {
121
+ throw new CircuitBreakerError(`요구사항을 ${MAX_CLARIFY_RETRIES}회 이상 확정하지 못했습니다. 작업 설명을 더 명확히 해주세요.`);
122
+ }
123
+ }
124
+ else if (state.phase !== Phase.CLARIFY) {
125
+ state.clarifyRetries = 0;
126
+ }
127
+ // 상태 업데이트
128
+ if (transition.verdict) {
129
+ if (transition.verdict.pass) {
130
+ logPhaseResult(state.phase, true);
131
+ state.verifyPass++;
132
+ state.consecutiveFailures = 0;
133
+ const totalRequired = state.goalConfirmed?.isRefactoring ? 5 : 2;
134
+ logInfo(`검증 통과 (${state.verifyPass}/${totalRequired})`);
135
+ }
136
+ else {
137
+ logPhaseResult(state.phase, false);
138
+ state.verifyPass = 0;
139
+ state.consecutiveFailures++;
140
+ state.failureHistory.push(transition.verdict.reason);
141
+ logWarn(`검증 실패: ${transition.verdict.reason.slice(0, 200)}`);
142
+ }
143
+ }
144
+ else {
145
+ logPhaseResult(state.phase, true);
146
+ }
147
+ state.phase = transition.nextPhase;
148
+ saveState(workingDir, state);
149
+ transientErrors = 0; // 단계 성공 시 일시적 오류 카운터 리셋
150
+ }
151
+ catch (e) {
152
+ // 서킷 브레이커는 즉시 전파 — 유일한 하드 스톱
153
+ if (e instanceof CircuitBreakerError)
154
+ throw e;
155
+ // 그 외 모든 오류: 상태 저장 후 백오프 재시도 (절대 멈추지 않는다)
156
+ state.iterations--; // 실패한 반복은 카운트하지 않음
157
+ transientErrors++;
158
+ logWarn(`실행 오류 (${transientErrors}회): ${getErrorMessage(e)}`);
159
+ saveState(workingDir, state);
160
+ const backoffMs = Math.min(transientErrors * 10_000, 60_000);
161
+ logInfo(`${backoffMs / 1000}초 후 재시도합니다...`);
162
+ await new Promise(resolve => setTimeout(resolve, backoffMs));
163
+ continue;
164
+ }
165
+ }
166
+ if (state.phase === Phase.DONE) {
167
+ logSuccess("모든 작업이 완료되었습니다!");
168
+ }
169
+ }
170
+ catch (e) {
171
+ if (e instanceof CircuitBreakerError) {
172
+ logError(`서킷 브레이커 작동: ${e.message}`);
173
+ saveState(workingDir, state);
174
+ throw e;
175
+ }
176
+ else {
177
+ logError(`오류 발생: ${getErrorMessage(e)}`);
178
+ saveState(workingDir, state);
179
+ throw e;
180
+ }
181
+ }
182
+ finally {
183
+ process.removeListener("SIGINT", onSigInt);
184
+ process.removeListener("SIGTERM", onSigTerm);
185
+ }
186
+ }
187
+ function handlePhaseResult(state, text) {
188
+ switch (state.phase) {
189
+ case Phase.IMPLEMENT:
190
+ state.implementationSummary = text;
191
+ break;
192
+ case Phase.VERIFY:
193
+ state.lastVerifyResult = text;
194
+ break;
195
+ }
196
+ }
197
+ function buildExternalHelpPrompt(state) {
198
+ const recent = state.failureHistory.slice(-3).join("\n---\n");
199
+ return `다음 개발 작업에서 ${state.consecutiveFailures}회 연속 검증 실패가 발생했다.\n\n` +
200
+ `목표: ${state.goalConfirmed?.summary ?? state.goal}\n\n` +
201
+ `최근 실패 사유:\n${recent}\n\n` +
202
+ `이 문제를 해결하기 위한 구체적인 방법을 제안하라.`;
203
+ }
204
+ //# sourceMappingURL=orchestrator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"orchestrator.js","sourceRoot":"","sources":["../src/orchestrator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import { type GoalConfirmed, type PhaseConfig, type PhaseTransition, type RunState } from "./types.js";
2
+ export declare function buildPhaseConfig(state: RunState, cwd: string, externalAdvice?: string): PhaseConfig;
3
+ export declare function parseGoalConfirmed(text: string): GoalConfirmed | null;
4
+ export declare function resolveNextPhase(state: RunState, result: string): PhaseTransition;
package/dist/phases.js ADDED
@@ -0,0 +1,139 @@
1
+ // 단계별 설정 빌더: 각 Phase에 맞는 프롬프트/도구/플래그 조합
2
+ import { existsSync, readFileSync } from "node:fs";
3
+ import { join } from "node:path";
4
+ import { Phase } from "./types.js";
5
+ import { IMPLEMENTATION_RULES, VERIFICATION_RULES, UI_WORK_RULES, buildClarifyPrompt, buildImplementPrompt, buildVerifyPrompt, } from "./prompts.js";
6
+ // 비대화형 파이프 모드에서 plan 모드 블로킹 방지
7
+ const AUTONOMOUS_DIRECTIVE = "\n[자율 실행 모드] 비대화형 파이프 모드로 실행 중이다. 계획 수립 후 즉시 실행하라.";
8
+ // 외부 LLM 활용 지시 (#13: gemini/codex를 검증과 문제 해결에 적극 활용)
9
+ const LLM_COLLABORATION_DIRECTIVE = "\n[외부 LLM 활용] 면밀한 검증이나 문제 해결이 필요하면 gemini(gemini -p \"질문\")나 codex(codex exec \"질문\")를 Bash로 호출하여 독립적 의견을 구하라.";
10
+ // #7: 프로젝트 의존성 파일을 읽어서 중복 설치/버전 충돌 방지
11
+ function readDependencyInfo(cwd) {
12
+ const candidates = [
13
+ "package.json", "requirements.txt", "pyproject.toml",
14
+ "go.mod", "Cargo.toml", "pubspec.yaml", "Gemfile",
15
+ ];
16
+ for (const filename of candidates) {
17
+ const filePath = join(cwd, filename);
18
+ if (existsSync(filePath)) {
19
+ try {
20
+ const content = readFileSync(filePath, "utf-8").slice(0, 5000);
21
+ return `파일: ${filename}\n${content}`;
22
+ }
23
+ catch {
24
+ continue;
25
+ }
26
+ }
27
+ }
28
+ return null;
29
+ }
30
+ export function buildPhaseConfig(state, cwd, externalAdvice) {
31
+ switch (state.phase) {
32
+ case Phase.CLARIFY:
33
+ return {
34
+ phase: Phase.CLARIFY,
35
+ prompt: buildClarifyPrompt(state.goal, state.clarifyMessages),
36
+ systemPromptAppend: "",
37
+ skipPermissions: false,
38
+ cwd,
39
+ };
40
+ case Phase.IMPLEMENT: {
41
+ if (!state.goalConfirmed) {
42
+ throw new Error("IMPLEMENT 단계에 goalConfirmed가 없습니다. 상태가 손상되었을 수 있습니다.");
43
+ }
44
+ const depsSummary = readDependencyInfo(cwd) ?? undefined;
45
+ let systemPrompt = IMPLEMENTATION_RULES + LLM_COLLABORATION_DIRECTIVE + AUTONOMOUS_DIRECTIVE;
46
+ if (state.goalConfirmed.isUIWork) {
47
+ systemPrompt += UI_WORK_RULES;
48
+ }
49
+ return {
50
+ phase: Phase.IMPLEMENT,
51
+ prompt: buildImplementPrompt(state.goalConfirmed, state.failureHistory, externalAdvice, depsSummary),
52
+ systemPromptAppend: systemPrompt,
53
+ skipPermissions: true,
54
+ cwd,
55
+ };
56
+ }
57
+ case Phase.VERIFY: {
58
+ if (!state.goalConfirmed) {
59
+ throw new Error("VERIFY 단계에 goalConfirmed가 없습니다. 상태가 손상되었을 수 있습니다.");
60
+ }
61
+ return {
62
+ phase: Phase.VERIFY,
63
+ prompt: buildVerifyPrompt(state.goalConfirmed, state.implementationSummary ?? ""),
64
+ systemPromptAppend: VERIFICATION_RULES + LLM_COLLABORATION_DIRECTIVE + AUTONOMOUS_DIRECTIVE,
65
+ allowedTools: ["Read", "Glob", "Grep", "Bash"],
66
+ skipPermissions: true,
67
+ cwd,
68
+ };
69
+ }
70
+ default:
71
+ throw new Error(`알 수 없는 단계: ${state.phase}`);
72
+ }
73
+ }
74
+ // 검증 결과에서 PASS/FAIL 판정 추출
75
+ function parseVerdict(text) {
76
+ const passMatch = text.match(/<verdict>\s*PASS\s*<\/verdict>/i);
77
+ if (passMatch) {
78
+ return { pass: true, reason: "" };
79
+ }
80
+ const failMatch = text.match(/<verdict>\s*FAIL:\s*([\s\S]*?)<\/verdict>/i);
81
+ if (failMatch) {
82
+ return { pass: false, reason: failMatch[1].trim() };
83
+ }
84
+ // 태그가 없으면 FAIL (안전 우선 — 태그 없는 텍스트에서 PASS를 추론하지 않음)
85
+ return { pass: false, reason: "판정 태그를 찾을 수 없습니다. 재검증이 필요합니다." };
86
+ }
87
+ // CLARIFY 결과에서 GoalConfirmed 추출 (런타임 타입 검증 포함)
88
+ export function parseGoalConfirmed(text) {
89
+ const match = text.match(/<goal_confirmed>\s*([\s\S]*?)\s*<\/goal_confirmed>/);
90
+ if (!match)
91
+ return null;
92
+ try {
93
+ const obj = JSON.parse(match[1]);
94
+ // 런타임 타입 검증
95
+ if (typeof obj !== "object" || obj === null ||
96
+ typeof obj.summary !== "string" ||
97
+ !Array.isArray(obj.tasks) ||
98
+ obj.tasks.length === 0 ||
99
+ !obj.tasks.every((t) => typeof t === "string") ||
100
+ !Array.isArray(obj.completionCriteria) ||
101
+ obj.completionCriteria.length === 0 ||
102
+ !obj.completionCriteria.every((c) => typeof c === "string")) {
103
+ return null;
104
+ }
105
+ return obj;
106
+ }
107
+ catch {
108
+ return null;
109
+ }
110
+ }
111
+ // 다음 단계 결정 — VERIFY PASS N회 연속 → DONE, FAIL → IMPLEMENT
112
+ // 일반 작업: 2회 연속 (verifyPass >= 1), 리팩토링: 5회 연속 (verifyPass >= 4)
113
+ export function resolveNextPhase(state, result) {
114
+ switch (state.phase) {
115
+ case Phase.CLARIFY: {
116
+ if (!state.goalConfirmed) {
117
+ return { nextPhase: Phase.CLARIFY, verdict: null };
118
+ }
119
+ return { nextPhase: Phase.IMPLEMENT, verdict: null };
120
+ }
121
+ case Phase.IMPLEMENT:
122
+ return { nextPhase: Phase.VERIFY, verdict: null };
123
+ case Phase.VERIFY: {
124
+ const verdict = parseVerdict(result);
125
+ if (!verdict.pass) {
126
+ return { nextPhase: Phase.IMPLEMENT, verdict };
127
+ }
128
+ // 리팩토링: 5회 연속 검증 (3회 필요성 + 2회 안전성), 일반: 2회 연속
129
+ const requiredPasses = state.goalConfirmed?.isRefactoring ? 4 : 1;
130
+ if (state.verifyPass >= requiredPasses) {
131
+ return { nextPhase: Phase.DONE, verdict };
132
+ }
133
+ return { nextPhase: Phase.VERIFY, verdict };
134
+ }
135
+ default:
136
+ return { nextPhase: Phase.DONE, verdict: null };
137
+ }
138
+ }
139
+ //# sourceMappingURL=phases.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"phases.js","sourceRoot":"","sources":["../src/phases.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import type { ClarifyMessage, GoalConfirmed } from "./types.js";
2
+ export declare const IMPLEMENTATION_RULES = "[\uD544\uC218 \uAD6C\uD604 \uADDC\uCE59 - \uBC18\uB4DC\uC2DC \uC900\uC218]\n- \uBAA8\uB4E0 \uC694\uAD6C\uC0AC\uD56D\uC744 \uC644\uBCBD\uD788 \uAD6C\uD604\uD558\uB77C.\n- \uD504\uB85C\uB355\uC158 \uB808\uBCA8\uC758 \uC124\uACC4\uC640 \uCF54\uB4DC\uB97C \uAD6C\uD604\uD558\uB77C.\n- \uAE30\uC874 \uD504\uB85C\uC81D\uD2B8 \uAD6C\uC870\uC640 \uCF54\uB4DC\uBCA0\uC774\uC2A4\uB97C \uBD84\uC11D\uD558\uC5EC \uC774\uBBF8 \uC874\uC7AC\uD558\uB294 \uAC83\uC744 \uC911\uBCF5\uC73C\uB85C \uAD6C\uD604\uD558\uAC8C \uB418\uB294 \uAC83\uC740 \uC544\uB2CC\uC9C0 \uD655\uC778\uD558\uACE0 \uAC80\uC99D\uD558\uB77C.\n- \uAE30\uC874 \uCF54\uB4DC\uB97C \uC218\uC815\uD558\uAC70\uB098 \uAE30\uC874 \uC2DC\uC2A4\uD15C\uACFC \uC5F0\uB3D9\uD558\uB294 \uC791\uC5C5\uC774\uBA74, \uBA3C\uC800 \uD504\uB85C\uC81D\uD2B8 \uC804\uCCB4 \uAD6C\uC870\uC640 \uAD00\uB828 \uD30C\uC77C\uC744 \uD30C\uC545\uD55C \uD6C4 \uC791\uC5C5\uD558\uB77C.\n- \uD604\uC7AC \uD504\uB85C\uC81D\uD2B8\uC5D0\uC11C \uC0AC\uC6A9\uC911\uC774\uAC70\uB098 \uAD6C\uD604\uB418\uC5B4 \uC788\uB294 \uD50C\uB7EC\uADF8\uC778, SDK, API, \uB77C\uC774\uBE0C\uB7EC\uB9AC\uC758 \uBC84\uC804\uACFC \uD638\uD658\uC131\uC5D0 \uC720\uC758\uD558\uB77C.\n- \uACFC\uB3C4\uD55C \uC5D4\uC9C0\uB2C8\uC5B4\uB9C1\uC744 \uD558\uC9C0 \uB9D0\uB77C.\n- \uC6B0\uD68C\uD558\uB294 \uBC29\uBC95\uC774\uB098 \uAF3C\uC218\uB97C \uC4F0\uC9C0 \uB9D0\uB77C.\n- \uC548\uC804\uD558\uAC8C \uAD6C\uD604\uD558\uB77C.\n- \uB354\uC774\uC0C1 \uC4F0\uC774\uC9C0\uB3C4 \uC54A\uC73C\uBA74\uC11C \uC794\uC874\uD558\uB294 \uD30C\uC77C\uC774\uB098 \uC2A4\uD06C\uB9BD\uD2B8, \uCF54\uB4DC\uAC00 \uC788\uB294\uC9C0 \uD655\uC778\uD558\uB77C.\n- \uCDA9\uB3CC\uC744 \uC77C\uC73C\uD0AC \uC218 \uC788\uB294 \uCF54\uB4DC\uB098 \uC2A4\uD06C\uB9BD\uD2B8, \uD30C\uC77C\uC774 \uC788\uB294\uC9C0 \uD655\uC778\uD558\uB77C.\n- \uC720\uC9C0\uBCF4\uC218\uAC00 \uCD5C\uB300\uD55C \uC6A9\uC774\uD558\uACE0 \uC9C0\uC18D\uAC00\uB2A5\uD558\uB3C4\uB85D \uC124\uACC4\uC640 \uCF54\uB4DC\uB97C \uAD6C\uD604\uD558\uB77C.\n- \uBE44\uC988\uB2C8\uC2A4 \uC6B4\uC601\uC744 \uC5C5\uACC4 \uCD5C\uACE0 \uC218\uC900\uC73C\uB85C \uC81C\uB300\uB85C \uD560 \uC218 \uC788\uB294 \uC124\uACC4\uC640 \uCF54\uB4DC\uB85C \uAD6C\uD604\uD558\uB77C.\n- \uAE30\uC220\uBD80\uCC44\uAC00 \uC313\uC77C \uC6B0\uB824\uAC00 \uC788\uB294 \uAD6C\uC870\uB97C \uB9CC\uB4E4\uC9C0 \uB9D0\uB77C.\n- \uBCF4\uC548\uC5D0 \uCDE8\uC57D\uD558\uB3C4\uB85D \uAD6C\uD604\uD558\uC9C0 \uB9D0\uB77C.\n- \uAD6C\uD604\uD558\uACE0 \uB098\uC11C, \uC798 \uAD6C\uD604\uB418\uC5C8\uB294\uC9C0 \uBA74\uBC00\uD788 \uAC80\uC99D\uD558\uB77C.\n- Unity \uD504\uB85C\uC81D\uD2B8\uAC00 \uC544\uB2CC \uACBD\uC6B0 \uC544\uC774\uCF58\uC740 \uBC18\uB4DC\uC2DC PNG\uAC00 \uC544\uB2CC SVG\uB85C \uAD6C\uD604\uD558\uB77C.";
3
+ export declare const VERIFICATION_RULES = "[\uD544\uC218 \uAC80\uC99D \uADDC\uCE59 - \uBC18\uB4DC\uC2DC \uC900\uC218]\n- \uBAA8\uB450 \uC798 \uAD6C\uD604\uB418\uC5C8\uB294\uC9C0 \uBA74\uBC00\uD788 \uAC80\uC99D\uD558\uB77C.\n- \uD504\uB85C\uB355\uC158 \uB808\uBCA8\uC758 \uC124\uACC4\uC774\uACE0 \uCF54\uB4DC\uC778\uC9C0 \uAC80\uC99D\uD558\uB77C.\n- \uACFC\uB3C4\uD55C \uC5D4\uC9C0\uB2C8\uC5B4\uB9C1\uC740 \uC5C6\uC5C8\uB294\uC9C0 \uAC80\uC99D\uD558\uB77C.\n- \uC6B0\uD68C\uD558\uB294 \uBC29\uBC95\uC774\uB098 \uAF3C\uC218\uB97C \uC4F0\uC9C0\uB294 \uC54A\uC558\uB294\uC9C0 \uAC80\uC99D\uD558\uB77C.\n- \uB354\uC774\uC0C1 \uC4F0\uC774\uC9C0\uB3C4 \uC54A\uC73C\uBA74\uC11C \uC794\uC874\uD558\uB294 \uD30C\uC77C\uC774\uB098 \uC2A4\uD06C\uB9BD\uD2B8, \uCF54\uB4DC\uAC00 \uC788\uB294\uC9C0 \uD655\uC778\uD558\uB77C.\n- \uCDA9\uB3CC\uC744 \uC77C\uC73C\uD0AC \uC218 \uC788\uB294 \uCF54\uB4DC\uB098 \uC2A4\uD06C\uB9BD\uD2B8, \uD30C\uC77C\uC774 \uC788\uB294\uC9C0 \uD655\uC778\uD558\uB77C.\n- \uBE44\uC6A9\uC774 \uC99D\uAC00\uD558\uAC70\uB098, \uC131\uB2A5\uC774 \uC545\uD654\uB418\uAC70\uB098, \uBE44\uD6A8\uC728\uC774 \uCD08\uB798\uB418\uB294 \uBB38\uC81C\uAC00 \uC5C6\uB294\uC9C0 \uAC80\uC99D\uD558\uB77C.\n- \uC548\uC804\uD558\uAC8C \uAD6C\uD604\uB418\uC5C8\uB294\uC9C0 \uAC80\uC99D\uD558\uB77C.\n- \uC720\uC9C0\uBCF4\uC218\uAC00 \uCD5C\uB300\uD55C \uC6A9\uC774\uD558\uACE0 \uC9C0\uC18D\uAC00\uB2A5\uD55C \uC124\uACC4\uC640 \uCF54\uB4DC\uC778\uC9C0 \uAC80\uC99D\uD558\uB77C.\n- \uD639\uC2DC \uC548\uC88B\uC740 \uC2A4\uD30C\uAC8C\uD2F0 \uCF54\uB4DC\uAC00 \uC788\uB294\uC9C0 \uC810\uAC80\uD558\uB77C.\n- \uBE44\uC988\uB2C8\uC2A4 \uC6B4\uC601\uC744 \uC5C5\uACC4 \uCD5C\uACE0 \uC218\uC900\uC73C\uB85C \uC81C\uB300\uB85C \uD560 \uC218 \uC788\uB294 \uC124\uACC4\uC640 \uCF54\uB4DC\uC778\uC9C0 \uAC80\uC99D\uD558\uB77C.\n- \uAE30\uC220\uBD80\uCC44\uAC00 \uC313\uC77C \uC6B0\uB824\uAC00 \uC788\uB294 \uAD6C\uC870\uB294 \uC544\uB2CC\uC9C0 \uAC80\uC99D\uD558\uB77C.\n- \uBCF4\uC548 \uCDE8\uC57D\uC131\uC740 \uC5C6\uB294\uC9C0 \uC810\uAC80\uD558\uB77C.\n- \uB204\uB77D\uB41C \uAC83\uC774\uB098 \uBE60\uC9C4 \uAC83\uC774\uB098 \uC0DD\uB7B5\uB41C \uAC83\uC774 \uC5C6\uB294\uC9C0 \uC810\uAC80\uD558\uB77C.";
4
+ export declare const UI_WORK_RULES = "\n[UI/\uD504\uB860\uD2B8\uC5D4\uB4DC \uC791\uC5C5 \uADDC\uCE59]\n1\uCC28: Google Stitch\uB97C \uC0AC\uC6A9\uD558\uB77C. MCP\uAC00 \uC124\uC815\uB418\uC5B4 \uC788\uC73C\uBA74 MCP\uB85C, \uC544\uB2C8\uBA74 API\uB85C \uD65C\uC6A9\uD558\uB77C. \uD504\uB86C\uD504\uD2B8\uB85C \uB514\uC790\uC778\uC744 \uC0DD\uC131(Generate)\uD558\uACE0 \uC989\uC2DC \uCF54\uB4DC\uBCA0\uC774\uC2A4\uC5D0 \uBC18\uC601(Reflect)\uD558\uB77C.\n2\uCC28: \uC544\uB798 \uB808\uD37C\uB7F0\uC2A4 \uC0AC\uC774\uD2B8\uB97C \uD0D0\uC0C9\uD558\uC5EC \uB514\uC790\uC778 \uB808\uD37C\uB7F0\uC2A4\uB97C \uD655\uBCF4\uD558\uB77C.\n 21st.dev, Shadcn, Reactbits, Magic UI, Aceternity UI, Tailwind UI, Godly, Mobbin, Land-book, Lapa Ninja, awwwards, supahero, iconify, bentogrids\n3\uCC28: frontend-design \uD50C\uB7EC\uADF8\uC778\uC744 \uD65C\uC6A9\uD558\uB77C.\n4\uCC28: \uC790\uCCB4\uC801\uC73C\uB85C \uB514\uC790\uC778\uD558\uB77C. \uC704 \uBC29\uBC95\uB4E4\uC744 \uD63C\uD569 \uC0AC\uC6A9 \uAC00\uB2A5.\n- gemini\uB97C \uC801\uADF9 \uD638\uCD9C\uD558\uC5EC UI \uC791\uC5C5\uC5D0 \uD65C\uC6A9\uD558\uB77C (gemini -p \"\uD504\uB86C\uD504\uD2B8\").\n- \uBE44\uC8FC\uC5BC \uC644\uC131\uB3C4\uB97C \uBA40\uD2F0\uBAA8\uB2EC LLM\uC73C\uB85C \uD3C9\uAC00\uD558\uB77C.";
5
+ export declare function buildClarifyPrompt(goal: string, clarifyMessages?: ClarifyMessage[]): string;
6
+ export declare function buildImplementPrompt(goal: GoalConfirmed, failureHistory: string[], externalAdvice?: string, depsSummary?: string): string;
7
+ export declare function buildVerifyPrompt(goal: GoalConfirmed, implementationSummary: string): string;
@@ -0,0 +1,140 @@
1
+ // 프로그래밍적으로 100% 보장되는 프롬프트 템플릿
2
+ // .md 파일이 아닌 코드이므로 절대 건너뛸 수 없다
3
+ // --append-system-prompt로 주입되므로 CLAUDE.md와 달리 스킵/무시될 수 없다
4
+ // ─── 구현 프롬프트 (--append-system-prompt로 100% 주입 보장) ───
5
+ export const IMPLEMENTATION_RULES = `[필수 구현 규칙 - 반드시 준수]
6
+ - 모든 요구사항을 완벽히 구현하라.
7
+ - 프로덕션 레벨의 설계와 코드를 구현하라.
8
+ - 기존 프로젝트 구조와 코드베이스를 분석하여 이미 존재하는 것을 중복으로 구현하게 되는 것은 아닌지 확인하고 검증하라.
9
+ - 기존 코드를 수정하거나 기존 시스템과 연동하는 작업이면, 먼저 프로젝트 전체 구조와 관련 파일을 파악한 후 작업하라.
10
+ - 현재 프로젝트에서 사용중이거나 구현되어 있는 플러그인, SDK, API, 라이브러리의 버전과 호환성에 유의하라.
11
+ - 과도한 엔지니어링을 하지 말라.
12
+ - 우회하는 방법이나 꼼수를 쓰지 말라.
13
+ - 안전하게 구현하라.
14
+ - 더이상 쓰이지도 않으면서 잔존하는 파일이나 스크립트, 코드가 있는지 확인하라.
15
+ - 충돌을 일으킬 수 있는 코드나 스크립트, 파일이 있는지 확인하라.
16
+ - 유지보수가 최대한 용이하고 지속가능하도록 설계와 코드를 구현하라.
17
+ - 비즈니스 운영을 업계 최고 수준으로 제대로 할 수 있는 설계와 코드로 구현하라.
18
+ - 기술부채가 쌓일 우려가 있는 구조를 만들지 말라.
19
+ - 보안에 취약하도록 구현하지 말라.
20
+ - 구현하고 나서, 잘 구현되었는지 면밀히 검증하라.
21
+ - Unity 프로젝트가 아닌 경우 아이콘은 반드시 PNG가 아닌 SVG로 구현하라.`;
22
+ // ─── 검증 프롬프트 (--append-system-prompt로 100% 주입 보장) ───
23
+ export const VERIFICATION_RULES = `[필수 검증 규칙 - 반드시 준수]
24
+ - 모두 잘 구현되었는지 면밀히 검증하라.
25
+ - 프로덕션 레벨의 설계이고 코드인지 검증하라.
26
+ - 과도한 엔지니어링은 없었는지 검증하라.
27
+ - 우회하는 방법이나 꼼수를 쓰지는 않았는지 검증하라.
28
+ - 더이상 쓰이지도 않으면서 잔존하는 파일이나 스크립트, 코드가 있는지 확인하라.
29
+ - 충돌을 일으킬 수 있는 코드나 스크립트, 파일이 있는지 확인하라.
30
+ - 비용이 증가하거나, 성능이 악화되거나, 비효율이 초래되는 문제가 없는지 검증하라.
31
+ - 안전하게 구현되었는지 검증하라.
32
+ - 유지보수가 최대한 용이하고 지속가능한 설계와 코드인지 검증하라.
33
+ - 혹시 안좋은 스파게티 코드가 있는지 점검하라.
34
+ - 비즈니스 운영을 업계 최고 수준으로 제대로 할 수 있는 설계와 코드인지 검증하라.
35
+ - 기술부채가 쌓일 우려가 있는 구조는 아닌지 검증하라.
36
+ - 보안 취약성은 없는지 점검하라.
37
+ - 누락된 것이나 빠진 것이나 생략된 것이 없는지 점검하라.`;
38
+ // ─── UI/프론트엔드 작업 규칙 (isUIWork=true 시 주입) ───
39
+ export const UI_WORK_RULES = `\n[UI/프론트엔드 작업 규칙]
40
+ 1차: Google Stitch를 사용하라. MCP가 설정되어 있으면 MCP로, 아니면 API로 활용하라. 프롬프트로 디자인을 생성(Generate)하고 즉시 코드베이스에 반영(Reflect)하라.
41
+ 2차: 아래 레퍼런스 사이트를 탐색하여 디자인 레퍼런스를 확보하라.
42
+ 21st.dev, Shadcn, Reactbits, Magic UI, Aceternity UI, Tailwind UI, Godly, Mobbin, Land-book, Lapa Ninja, awwwards, supahero, iconify, bentogrids
43
+ 3차: frontend-design 플러그인을 활용하라.
44
+ 4차: 자체적으로 디자인하라. 위 방법들을 혼합 사용 가능.
45
+ - gemini를 적극 호출하여 UI 작업에 활용하라 (gemini -p "프롬프트").
46
+ - 비주얼 완성도를 멀티모달 LLM으로 평가하라.`;
47
+ // ─── 프롬프트 인젝션 방어: 사용자 입력에서 제어 태그 제거 ───
48
+ function sanitizeForPrompt(text) {
49
+ return text
50
+ .replace(/<\/?goal_confirmed>/gi, "")
51
+ .replace(/<\/?verdict>/gi, "");
52
+ }
53
+ // ─── 단계별 프롬프트 빌더 ───
54
+ export function buildClarifyPrompt(goal, clarifyMessages) {
55
+ const safeGoal = sanitizeForPrompt(goal);
56
+ let conversationSection = "";
57
+ if (clarifyMessages && clarifyMessages.length > 0) {
58
+ conversationSection = "\n\n[이전 대화]\n" + clarifyMessages.map(m => {
59
+ const safeContent = sanitizeForPrompt(m.content);
60
+ return m.role === "assistant"
61
+ ? `에이전트: ${safeContent}`
62
+ : `사용자: ${safeContent}`;
63
+ }).join("\n\n") + "\n\n위 대화를 고려하여, 이제 요구사항을 확정하거나 추가 질문을 하라.";
64
+ }
65
+ return `당신은 자율 개발 에이전트이다. 사용자의 요청을 분석하고 요구사항을 확정하라.
66
+
67
+ 사용자 요청: ${safeGoal}${conversationSection}
68
+
69
+ [요구사항 평가]
70
+ - 새 프로젝트는 가치와 문제 해결 관점에서 평가하라.
71
+ - 설계 변경이나 대규모 기능 추가는 본질을 훼손하지 않는지 성찰하라.
72
+ - 사용자에게 무작정 동조하지 말고 냉정하고 객관적으로 평가하라.
73
+
74
+ [지침]
75
+ 1. 요청이 명확하면 바로 요구사항을 확정하라.
76
+ 2. 요청이 불명확하면 질문하라.
77
+ 3. 구현에 필요한 전제조건(API 키, 환경 설정, 외부 서비스 등)을 사전에 확인하라. 작업 착수 후에는 사용자 상호작용이 불가능하다.
78
+ 4. 구현 방법이 불명확하면 확정 전에 먼저 파악하라.
79
+
80
+ [확정 전 점검 - goal_confirmed 출력 전 반드시 확인]
81
+ 1. 모든 태스크의 구현 방법을 알고 있는가?
82
+ 2. 필요한 전제조건이 모두 확인되었는가?
83
+ 3. 사용자에게 더 확인할 사항이 없는가?
84
+ 위 항목 중 하나라도 "아니오"이면 goal_confirmed를 출력하지 말고 질문하라.
85
+
86
+ 최종 출력 형식 (반드시 이 JSON 형식으로 출력):
87
+ <goal_confirmed>
88
+ {
89
+ "summary": "확정된 요구사항 요약",
90
+ "tasks": ["세부 태스크 1", "세부 태스크 2"],
91
+ "completionCriteria": ["완성 조건 1: 구체적으로 무엇이 되어야 완료인지", "완성 조건 2"],
92
+ "isRefactoring": false,
93
+ "isUIWork": false
94
+ }
95
+ </goal_confirmed>
96
+ isRefactoring: 기존 코드/구조의 리팩토링 작업이면 true (더 엄격한 5회 연속 검증 적용).
97
+ isUIWork: UI/프론트엔드/비주얼 작업이면 true (디자인 도구 및 레퍼런스 활용).`;
98
+ }
99
+ export function buildImplementPrompt(goal, failureHistory, externalAdvice, depsSummary) {
100
+ let prompt = `목표: ${goal.summary}\n태스크:\n${goal.tasks.map((t, i) => `${i + 1}. ${t}`).join("\n")}`;
101
+ prompt += `\n\n[완성 조건 - 아래 조건이 모두 충족되어야 완료]\n${goal.completionCriteria.map((c, i) => `${i + 1}. ${c}`).join("\n")}`;
102
+ if (depsSummary) {
103
+ prompt += `\n\n[현재 프로젝트 의존성 - 중복 설치/버전 충돌 방지]\n${depsSummary}`;
104
+ }
105
+ if (failureHistory.length > 0) {
106
+ const recent = failureHistory.slice(-3);
107
+ prompt += `\n\n[이전 검증 실패 사항 - 반드시 수정할 것]\n${recent.join("\n---\n")}`;
108
+ }
109
+ if (externalAdvice) {
110
+ prompt += `\n\n[외부 AI 조언 - 참고하여 구현할 것]\n${externalAdvice}`;
111
+ }
112
+ prompt += `\n\n작업 완료 후, 수행한 내용을 요약하라.`;
113
+ return prompt;
114
+ }
115
+ export function buildVerifyPrompt(goal, implementationSummary) {
116
+ return `당신은 독립적인 검증 리뷰어이다.
117
+
118
+ [원래 목표]
119
+ ${goal.summary}
120
+
121
+ [완성 조건]
122
+ ${goal.completionCriteria.map((c, i) => `${i + 1}. ${c}`).join("\n")}
123
+
124
+ [구현 요약]
125
+ ${implementationSummary}
126
+
127
+ [검증 절차]
128
+ 1. 수정된 모든 파일을 읽고 분석하라.
129
+ 2. 관련 테스트와 검증 명령을 실행하라.
130
+ 3. 위 완성 조건이 모두 충족되었는지 하나씩 확인하라.
131
+ 4. 회귀, 깨진 기능, 누락된 엣지 케이스를 점검하라.
132
+ 5. 콘솔/터미널 오류가 있는지 확인하라.
133
+
134
+ 최종 판정을 다음 형식으로 출력하라:
135
+ - 무결하면: <verdict>PASS</verdict>
136
+ - 문제있으면: <verdict>FAIL: [상세 사유]</verdict>
137
+
138
+ 비판적으로 검증하라. 형식적으로 통과시키지 말라.`;
139
+ }
140
+ //# sourceMappingURL=prompts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompts.js","sourceRoot":"","sources":["../src/prompts.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ import { type RunState } from "./types.js";
2
+ export declare function createInitialState(goal: string): RunState;
3
+ export declare function loadState(workingDir: string): RunState | null;
4
+ export declare function saveState(workingDir: string, state: RunState): void;
5
+ export declare function clearState(workingDir: string): void;
6
+ export declare function writePidFile(workingDir: string): void;
7
+ export declare function cleanupPidFile(workingDir: string): void;
8
+ export declare function isLocked(workingDir: string): boolean;
9
+ export declare function isCancelled(workingDir: string): boolean;
10
+ export declare function readClarifyAnswer(workingDir: string): string | null;
11
+ export declare function writeClarifyPending(workingDir: string, question: string): void;
12
+ export declare function ensureSodaIgnored(workingDir: string): void;