ebfce17b03
증상: 사용자가 기획서 + 폴더 주고 "여기 개발해줘" 요청 → ASTRA 가 파일 만들고
"개발 완료" 보고 → 실제 파일을 열면 class/함수 본문이 비어 있음
(def foo(): pass · 빈 class · imports only). 99% 확률 재발.
원인:
- 안전망 이미 존재 (selfReflectorHollow.ts 가 정규식으로 빈 깡통 감지)
- BUT 두 개 config 모두 OFF — selfReflectorEnabled (Phase A) +
selfReflectorExternalEnabled (Phase B)
- Phase A 켜면 [Self-Reflector Check] 블록이 답변에 노출 (UX 부작용),
Phase B 는 +1 LLM 호출 비용 — 부작용 때문에 기본 OFF
- 결과: 다수 사용자가 안전망 전혀 없는 상태로 코드 작성 → 빈 깡통 통과
Fix 3종:
1. Hollow check 를 selfReflector 와 분리 — 신규 설정 2개:
- g1nation.hollowCheck.enabled (boolean, 기본 ON) — action-tag 있는 모든
응답에 무조건 hollow 스캔. LLM 호출 0.
- g1nation.hollowCheck.autoRetry (boolean, 기본 ON) — 검출 시 1회 자동
재작업. Phase B 와 분리.
- dispatcher.ts 게이트 조건 교체
2. dev-impl 프롬프트 강화 (pipelineTemplates.ts) — [빈 깡통 금지] 5개 규칙:
- 파일은 하나씩 생성, 모든 함수 본문 완전 구현 후 다음 파일로
- 금지 패턴 명시: pass · ... · NotImplementedError · # TODO · 빈 class
- 인터페이스/추상 메서드만 빈 본문 OK
- 각 파일 생성 직후 자가 검증
- 최종 요약에 파일별 핵심 동작 한 줄씩
3. 기본값 변경 — 사용자 행동 없이 안전망 작동. 옛 selfReflector Phase A/B 는
그대로 OFF (UX 부작용 보존).
예상 효과: ~70-85% stub 감소. 남은 ~15% (작은 모델 attention 한계 / 큰 프로젝트)
는 per-file 순차 생성으로 v2.2.204+ 검토.
모델 한계 vs 로직 fix: 대부분 로직 fix 가능. 매우 작은 모델 (≤4B) 은 한계 더
빠름 — 더 큰 모델 (gemma-12b, qwen-32b) 권장.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
286 lines
16 KiB
TypeScript
286 lines
16 KiB
TypeScript
/**
|
|
* Built-in pipeline templates for 1인 기업 모드.
|
|
*
|
|
* These are *blueprints*, not data — they're surfaced in the manage panel's
|
|
* "템플릿에서 추가" dropdown so a non-developer user can stamp out a
|
|
* working pipeline in one click and then tweak the labels / 지시 / agent
|
|
* assignments in the card editor. Once stamped, the pipeline lives in
|
|
* `state.pipelines` like any other; templates themselves stay read-only in
|
|
* code so a future Astra version can ship improved defaults without
|
|
* trampling user edits.
|
|
*
|
|
* Why ship a template at all: the user's own description of the desired
|
|
* workflow ("작업 수락 → 기획 → 시장 조사 → … → QA → 배포") is exactly the
|
|
* shape this codifies. Without the template they'd have to author 13
|
|
* cards from scratch the first time they open the editor — which is
|
|
* exactly the friction we're trying to remove.
|
|
*/
|
|
import { PipelineDef } from './types';
|
|
|
|
export interface PipelineTemplate {
|
|
/** Stable id used by the UI dropdown and `applyTemplate` call. */
|
|
templateId: string;
|
|
/** Korean display name shown in the dropdown. */
|
|
name: string;
|
|
/** One-line description of when this template fits. */
|
|
description: string;
|
|
/**
|
|
* Default pipeline id when stamping. The UI will suggest this and let
|
|
* the user override before saving so two stamps don't collide.
|
|
*/
|
|
suggestedPipelineId: string;
|
|
/** Default human-readable name for the stamped pipeline. */
|
|
suggestedPipelineName: string;
|
|
/** Stage definitions — same shape as a saved PipelineDef.stages. */
|
|
stages: PipelineDef['stages'];
|
|
}
|
|
|
|
/**
|
|
* "풀 프로덕트 개발" — the user's described workflow, codified:
|
|
* 1. 작업 수락 — CEO 브리프 (자동, 별도 stage 아님)
|
|
* 2. 기획 논의 — planner
|
|
* 3. 시장 조사 — researcher
|
|
* 4. 트렌드 조사 — researcher
|
|
* 5. 방향성 정의 — planner
|
|
* 6. 기획문서 작성 — planner
|
|
* 7. 기획문서 검토 — inspector (재작업 발견 시 → 6번 loop-back)
|
|
* 8. 기획문서 최종본 — planner
|
|
* 9. 개발 설계 — developer
|
|
* 10. 설계 검토 — inspector (재작업 발견 시 → 9번 loop-back)
|
|
* 11. 개발 진행 — developer
|
|
* 12. QA 진행 — qa (버그 발견 시 → 11번 loop-back)
|
|
* 13. 라이브 배포 — developer
|
|
*
|
|
* 1번 "작업 수락"은 별도 stage가 아니라 CEO의 브리프 발신 — 모든 pipeline
|
|
* turn은 자동으로 brief를 생성해 `{{brief}}` 토큰으로 사용 가능하다.
|
|
*
|
|
* 지시 템플릿은 작은 LLM이 가장 자주 어기는 두 가지 — (a) 기획 문맥 잊기,
|
|
* (b) 단순 코드만 던지기 — 를 강하게 누른다. 사용자가 처음 보면 길어
|
|
* 보일 수 있는데, "이 단계에서 정확히 뭘 해야 하나" 가이드가 필요한
|
|
* 작은 모델 (gemma e2b·4b 등)에서 결과 품질을 크게 좌우한다.
|
|
*/
|
|
const FULL_PRODUCT_DEV: PipelineTemplate = {
|
|
templateId: 'full-product-dev',
|
|
name: '풀 프로덕트 개발 (13단계)',
|
|
description: '기획 → 리서치 → 기획서 → 검토 → 설계 → 개발 → QA → 배포. 기획 누락 없이 풀 사이클을 도는 표준 워크플로.',
|
|
suggestedPipelineId: 'product-dev',
|
|
suggestedPipelineName: '제품 개발 파이프라인',
|
|
stages: [
|
|
// 모든 stage가 *직군*만 지정하고 담당자는 비워둠 (agentId 생략). dispatcher가
|
|
// stage 진입 시 CEO에게 1회 LLM 콜로 적임자 선택. 활성 후보가 1명뿐이면
|
|
// 콜 없이 그 사람을 쓴다. 사용자의 의도("CEO가 배분 결정")와 일치.
|
|
{
|
|
id: 'plan-discuss',
|
|
label: '기획 논의',
|
|
roleCategory: 'planner',
|
|
instructionTemplate:
|
|
'사용자 요청: {{userPrompt}}\n\n' +
|
|
'이번 작업의 목표·사용자·성공 기준을 정리하세요. 결정 사항이 아니라 *논의 정리* 단계입니다.\n' +
|
|
'- 누구를 위한 결과물인가\n- 핵심 가치 한 줄\n- 우리가 모르는 것 / 더 알아봐야 할 것\n- 위험 요소',
|
|
},
|
|
{
|
|
id: 'market-research',
|
|
label: '시장 조사',
|
|
roleCategory: 'researcher',
|
|
instructionTemplate:
|
|
'기획 논의 정리: {{stage.plan-discuss}}\n\n' +
|
|
'위 맥락에서 *시장 측면*을 조사하세요. 추측 금지, 데이터/사례 기반.\n' +
|
|
'- 비슷한 시도가 이미 있나 (3개 이상)\n- 시장 크기·고객 페르소나\n- 가격대·수익화 패턴\n결과는 "출처(또는 일반론임을 명시)" 표시.',
|
|
},
|
|
{
|
|
id: 'trend-research',
|
|
label: '트렌드 조사',
|
|
roleCategory: 'researcher',
|
|
instructionTemplate:
|
|
'기획 논의: {{stage.plan-discuss}}\n시장 조사 결과: {{stage.market-research}}\n\n' +
|
|
'*최근 트렌드*를 조사하세요. 6개월 이내 변화를 우선.\n' +
|
|
'- 떠오르는 키워드/패턴\n- 사용자 기대치 변화\n- 우리가 활용할 수 있는 기술/문화 신호',
|
|
},
|
|
{
|
|
id: 'direction',
|
|
label: '방향성 정의',
|
|
roleCategory: 'planner',
|
|
instructionTemplate:
|
|
'기획 논의: {{stage.plan-discuss}}\n시장: {{stage.market-research}}\n트렌드: {{stage.trend-research}}\n\n' +
|
|
'위 3개를 종합해 *우리가 갈 방향*을 한 문단으로 결론지어요.\n포함:\n' +
|
|
'- 무엇을 만들 것인가 (제품 한 줄 설명)\n- 누가 첫 사용자인가\n- 안 만들 것 (out of scope)\n- 성공 판단 기준 1~3가지',
|
|
},
|
|
{
|
|
id: 'plan-draft',
|
|
label: '기획문서 초안',
|
|
roleCategory: 'planner',
|
|
instructionTemplate:
|
|
'방향성: {{stage.direction}}\n\n' +
|
|
'이 방향에 맞는 *기획서 초안*을 마크다운으로 작성하세요.\n' +
|
|
'필수 섹션:\n' +
|
|
'## 배경\n## 목표\n## 핵심 사용자 시나리오 (3개 이상, 구체적)\n## 주요 기능 목록\n## 비기능 요구사항\n## 측정 지표 (KPI)\n## 미래 확장 / 비-목표\n\n' +
|
|
'아직 *최종본 아님* — 검토자가 피드백 줄 수 있도록 가정·미확정 사항을 명시하세요.',
|
|
},
|
|
{
|
|
id: 'plan-review',
|
|
label: '기획문서 검토',
|
|
roleCategory: 'inspector',
|
|
instructionTemplate:
|
|
'검토 대상: {{stage.plan-draft}}\n\n' +
|
|
'*감리* 관점에서 기획서를 검토하세요. 칭찬 X, 구체적 피드백 O.\n' +
|
|
'확인 사항:\n- 시나리오가 구체적인가 ("사용자가 X를 한다" vs "사용자가 잘 쓴다")\n' +
|
|
'- 기능 vs 시나리오 매핑이 1:1로 되는가\n- 측정 가능한 성공 기준이 있는가\n- 빠진 케이스/엣지 케이스\n\n' +
|
|
'결론은 반드시 "✅ 승인" 또는 "❌ 재작업 필요: <항목 나열>" 로 시작.',
|
|
loopBackPattern: '재작업 필요|reject|보완 필요',
|
|
loopBackTo: 'plan-draft',
|
|
maxIterations: 3,
|
|
},
|
|
{
|
|
id: 'plan-final',
|
|
label: '기획문서 최종본',
|
|
roleCategory: 'planner',
|
|
instructionTemplate:
|
|
'초안: {{stage.plan-draft}}\n검토 피드백: {{stage.plan-review}}\n\n' +
|
|
'피드백을 모두 반영해 *최종 기획서*를 다시 쓰세요. 다음 단계(개발 설계)에서 그대로 사양서로 쓸 정도로 명확해야 합니다.',
|
|
},
|
|
{
|
|
id: 'dev-design',
|
|
label: '개발 설계',
|
|
roleCategory: 'developer',
|
|
instructionTemplate:
|
|
'최종 기획서: {{stage.plan-final}}\n\n' +
|
|
'이 기획서 기준으로 *개발 설계 문서*를 작성하세요. 아직 코드는 쓰지 않습니다.\n' +
|
|
'포함:\n## 데이터 모델\n## 컴포넌트/모듈 분할\n## 외부 의존성\n## 단계별 구현 순서 (체크리스트)\n## 테스트 전략\n## 알려진 리스크',
|
|
},
|
|
{
|
|
id: 'design-review',
|
|
label: '설계 검토',
|
|
roleCategory: 'inspector',
|
|
instructionTemplate:
|
|
'설계 문서: {{stage.dev-design}}\n기획서: {{stage.plan-final}}\n\n' +
|
|
'설계가 기획 의도를 모두 커버하는지 *감리*하세요. 누락된 시나리오·과도한 over-engineering이 있나.\n' +
|
|
'결론은 "✅ 승인" 또는 "❌ 재작업 필요: ..." 로 시작.',
|
|
loopBackPattern: '재작업 필요|reject|보완 필요',
|
|
loopBackTo: 'dev-design',
|
|
maxIterations: 2,
|
|
},
|
|
{
|
|
id: 'dev-impl',
|
|
label: '개발 진행',
|
|
roleCategory: 'developer',
|
|
instructionTemplate:
|
|
'설계: {{stage.dev-design}}\n기획서: {{stage.plan-final}}\n\n' +
|
|
'설계대로 *실제 코드를 작성*하세요. 반드시 ConnectAI 액션 태그(`<create_file>`, `<edit_file>`, `<run_command>`)를 사용해 디스크에 떨어지도록.\n' +
|
|
'코드 블록만 보여주고 "생성 완료"라고 말하면 디스크엔 아무것도 안 만들어집니다.\n\n' +
|
|
'[빈 깡통 금지 — 가장 자주 발생하는 실패 패턴]\n' +
|
|
'1. 파일은 **하나씩** 생성. 한 파일 안의 **모든 함수·메서드·클래스 본문을 완전히 구현** 후 다음 파일로.\n' +
|
|
'2. **금지 패턴**: `def foo(): pass` · `def foo(): ...` · `def foo(): raise NotImplementedError` · `def foo(): # TODO` · 빈 class 본문 (`class Foo: pass`) · imports 만 있는 파일.\n' +
|
|
'3. 함수 본문이 정말 비어도 되는 경우는 *인터페이스/추상 메서드* 만. 나머지는 **무조건 동작하는 코드** 작성. 단순화는 OK, 빈 깡통은 NO.\n' +
|
|
'4. 각 파일 생성 직후 한 줄 자가 검증: "이 파일이 정말 동작하나? 빈 본문 없나?". 없으면 보강 후 `<edit_file>` 로 재기록.\n' +
|
|
'5. 모든 파일 생성 끝나면 *최종 요약* 에 (a) 생성된 파일 수 (b) 각 파일의 핵심 함수 동작 한 줄씩 명시.\n\n' +
|
|
'⚠️ "구조만 잡고 추후 구현" 패턴은 즉시 검출돼 자동 재작업이 트리거됩니다. 처음부터 본문까지 완전 구현하세요.',
|
|
},
|
|
{
|
|
id: 'qa',
|
|
label: 'QA 진행',
|
|
roleCategory: 'qa',
|
|
instructionTemplate:
|
|
'구현 결과: {{stage.dev-impl}}\n기획서: {{stage.plan-final}}\n\n' +
|
|
'*테스트 시나리오를 직접 실행*해 기능을 검증하세요. 케이스별로 PASS/FAIL 명확히 적고, 실패 시 재현 방법을 적어요.\n' +
|
|
'결론은 "✅ 모든 케이스 통과" 또는 "❌ 버그 발견: ..." 로 시작 (loop-back regex가 이걸 봅니다).',
|
|
loopBackPattern: '버그 발견|❌|버그|오류|실패',
|
|
loopBackTo: 'dev-impl',
|
|
maxIterations: 4,
|
|
},
|
|
{
|
|
id: 'deploy',
|
|
label: '라이브 배포',
|
|
roleCategory: 'developer',
|
|
instructionTemplate:
|
|
'QA 통과 결과: {{stage.qa}}\n\n' +
|
|
'배포 절차를 *실행*하세요. README 갱신, 버전 태깅, 배포 스크립트 실행 등 필요한 명령은 `<run_command>` 로.\n' +
|
|
'마지막에 배포된 상태 요약과 사용자에게 안내할 한 줄 (📝 다음).',
|
|
},
|
|
],
|
|
};
|
|
|
|
/**
|
|
* 짧은 "기획만" 워크플로 — 사용자가 기획문서까지만 필요한 경우. 각 산출물
|
|
* stage에 3-way 검수 사이클을 켜서 셋(작업자 + 감리 + CEO) 합의로 통과
|
|
* 시키는 패턴을 보여준다. 풀-프로덕트와 달리 별도 review stage를 두지 않고
|
|
* 사이클로 합쳐서 빠르게 끝낸다.
|
|
*/
|
|
const PLAN_ONLY: PipelineTemplate = {
|
|
templateId: 'plan-only',
|
|
name: '기획서까지만 (검수 사이클)',
|
|
description: '시장 조사 → 방향성 → 기획서. 각 산출물 stage에서 검수자 + CEO 합의로 통과시키는 짧은 워크플로.',
|
|
suggestedPipelineId: 'plan-only',
|
|
suggestedPipelineName: '기획서 작성',
|
|
stages: [
|
|
{
|
|
id: 'market-research',
|
|
label: '시장 조사',
|
|
roleCategory: 'researcher',
|
|
instructionTemplate:
|
|
'사용자 요청: {{userPrompt}}\n\n' +
|
|
'이 요청 맥락에서 *시장 측면*을 조사하세요. 추측 금지, 데이터/사례 기반.\n' +
|
|
'- 비슷한 시도가 이미 있나 (3개 이상)\n- 시장 크기·고객 페르소나\n- 가격대·수익화 패턴\n' +
|
|
'결과는 "출처(또는 일반론임을 명시)" 표시.',
|
|
},
|
|
{
|
|
id: 'direction',
|
|
label: '방향성 정의',
|
|
roleCategory: 'planner',
|
|
instructionTemplate:
|
|
'사용자 요청: {{userPrompt}}\n시장 조사: {{stage.market-research}}\n\n' +
|
|
'*우리가 갈 방향*을 한 문단으로 결론짓고 측정 가능한 성공 기준을 1~3개 적으세요.',
|
|
reviewWith: 'inspector',
|
|
reviewMaxRounds: 3,
|
|
},
|
|
{
|
|
id: 'plan-doc',
|
|
label: '기획문서',
|
|
roleCategory: 'planner',
|
|
instructionTemplate:
|
|
'방향성: {{stage.direction}}\n\n' +
|
|
'아래 섹션 구조로 *기획서*를 마크다운으로 작성하세요. 합의 통과 후엔 사장님께 그대로 전달됩니다.\n\n' +
|
|
'## 배경\n## 목표\n## 핵심 사용자 시나리오 (3개 이상, 구체적)\n## 주요 기능 목록\n## 비기능 요구사항\n## 측정 지표 (KPI)\n## 미래 확장 / 비-목표',
|
|
reviewWith: 'inspector',
|
|
reviewMaxRounds: 3,
|
|
},
|
|
],
|
|
};
|
|
|
|
/**
|
|
* "개발까지만" — FULL_PRODUCT_DEV 의 1~10 단계 (plan-discuss ~ dev-impl) 만 진행.
|
|
* QA·배포는 사용자가 코드 받아본 뒤 수동 처리하길 원하는 경우. dev-impl 종료
|
|
* 직후 CEO 합산 보고로 turn 종료. design-review 의 dev-design loop-back 은 유지.
|
|
*
|
|
* stages 는 FULL_PRODUCT_DEV.stages.slice(0, 10) 으로 *참조 공유* — 사용자가
|
|
* 템플릿 stamp 시 deep-copy 되므로 본 정의 객체는 read-only 안전.
|
|
*/
|
|
const DEV_ONLY: PipelineTemplate = {
|
|
templateId: 'dev-only',
|
|
name: '개발까지만 (10단계)',
|
|
description: '풀 워크플로에서 QA·배포 단계를 뺀 버전. 기획 → 개발까지 만들고 검증·배포는 사용자가 직접 챙깁니다.',
|
|
suggestedPipelineId: 'dev-only',
|
|
suggestedPipelineName: '기획→개발 파이프라인',
|
|
stages: FULL_PRODUCT_DEV.stages.slice(0, 10),
|
|
};
|
|
|
|
/** Read-only registry of templates the UI surfaces. */
|
|
export const PIPELINE_TEMPLATES: PipelineTemplate[] = [
|
|
PLAN_ONLY,
|
|
DEV_ONLY,
|
|
FULL_PRODUCT_DEV,
|
|
];
|
|
|
|
/**
|
|
* 스코프 단축 표기 — 사용자가 사이드바에서 한 번에 보고 선택할 수 있는 3-way 라벨.
|
|
* 각 키는 PIPELINE_TEMPLATES 의 templateId 와 1:1. 매핑 변경 시 UI 동기화 필요.
|
|
*/
|
|
export const SCOPE_PRESETS = [
|
|
{ templateId: 'plan-only', shortLabel: '기획만', longLabel: '기획서까지만' },
|
|
{ templateId: 'dev-only', shortLabel: '개발까지', longLabel: '개발까지만' },
|
|
{ templateId: 'full-product-dev', shortLabel: '풀', longLabel: '배포까지 풀 파이프라인' },
|
|
] as const;
|
|
|
|
export function getPipelineTemplate(id: string): PipelineTemplate | undefined {
|
|
return PIPELINE_TEMPLATES.find((t) => t.templateId === id);
|
|
}
|