Pipeline Architecture Spec — C4I Framework
Status: draft Created: 2026-04-18 결정자: 회장 근거: 다이아몬드 토론 2회 (A07 구조적 복구 + 파이프라인 아키텍처)
1. 개요
1.1 현재 문제
현재 파이프라인(server/src/index.ts)은 모놀리스 핸들러 구조다:
- 메시지 수신 → CEO 분석 → C레벨 지시 → 워커 실행 → 결과 수집이 하나의 거대한 함수 안에 뒤섞여 있음
- 계층 간 통신이 프롬프트 텍스트 파싱(
[DELEGATE]태그 정규식)에 의존 → 깨질 수 있는 경로 존재 - 리더 계층이 dead code (정의만 있고 호출 0회)
- 명령은 아래로만 흐르고, 보고↑ 채널 부재
- 에러 시 구조적 복구 없이 catch-log-continue
1.2 왜 C4I인가
BigBossOS는 계급 조직이다 (회장→CEO→C레벨→리더→워커). 군사 지휘통제체계(C4I: Command, Control, Communications, Intelligence)가 이 구조에 가장 자연스럽게 매핑된다.
C4I를 뼈대로 잡고, 다른 체계에서 이점만 차용한다:
| 차용 출처 | 가져오는 것 | 적용 위치 |
|---|---|---|
| 컴파일러 | IR(중간 표현) 타입 | 계층 간 데이터 규격 — 타입 불일치 시 컴파일 에러 |
| OS 커널 | syscall = 구조화 출력 | 계층 간 통신 — 프롬프트 해석 제거, 구조적 강제 |
| Unix 철학 | 독립 모듈 | 공정별 분리 — 하나 고장나도 다른 공정 무관 |
| 원자력발전소 | SIL 등급 + SCRAM | 안전 체계 — 위험도별 검증 단계 자동 결정 |
| 도요타 TPS | 안돈 시그널 | 이상 감지 시 일시정지 + 상위 판단 요청 |
| 항공관제 | 핸드오프 프로토콜 + 스트립 | 계층 간 인계 3단계 + 작업 추적 |
| 잠수함 운용 | 침묵 항해 + 구획화 + 당직 | 제한 자원 하 독립 운용, 자원 격리, 에너지 관리 |
1.3 설계 원칙
- 프롬프트 믿지 말고 구조화 — 행동은 코드 플로우(choke point)로 강제. 프롬프트 의도 서술 금지.
- 증상치료 금지, 근본해결만 — 현실적 타협 무관용. 초기/중기/장기 분할 금지.
- WHAT vs WHO 분리 — C레벨은 WHAT(도메인 과업)만 출력. WHO(인원 배치)는 시스템이 결정.
- 순차 실행 + ViewHolder — 메모리/CPU 제약(셀프호스팅). C레벨 듀얼트랙만 예외.
- 무료 전용 — 유료 서비스 회장 승인 필수.
2. Command (지휘)
2.1 지휘 체계
회장 (Chairman) ──── 인간. 최종 권한. 시스템 외부.
└─ CEO ─────────── AI. 조직 수준 의사결정, C레벨 인사권.
└─ C-Level ── AI. 도메인 정책 수립 (CTO/COO/CFO/CMO/CPO/CISO).
└─ Leader ── AI. 구현 계획 수립 (backend_lead, frontend_lead, ...).
└─ Worker ── AI. 코드 실행. 유일한 코드 작성 계층.
하향 단방향 명령 원칙: 상위→직속 하위만 명령 가능. 계층 건너뛰기 금지.
CEO → C-Level만
C-Level → Leader만
Leader → Worker만
Worker → 명령 불가 (보고만 가능)
2.2 OPORD (작전명령서) 구조
NATO 작전명령서 5단계를 IR 타입의 필수 필드로 강제한다. 계층별로 필수 필드가 다르다:
| 필드 | 설명 | CEO→C레벨 | C레벨→리더 | 리더→워커 |
|---|---|---|---|---|
situation | 현재 프로젝트/도메인 상태 | 필수 | 선택 | - |
mission | 이번 사이클에서 달성할 것 | 필수 | 필수 | 필수 |
execution | 구체적 과업 분해 | 필수 | 필수 | 필수 |
sustainment | 토큰/메모리/시간 제약 | 필수 | 필수 | 선택 |
commandSignal | 보고 경로, 에스컬레이션 조건 | 필수 | 선택 | - |
필수 필드 누락 시 타입 에러 → 컴파일 불가. 런타임에 도달하지 않는다.
3. Control (통제)
3.1 계층별 권한 범위
각 계층은 할 수 있는 것과 절대 하면 안 되는 것(ROE)이 정의된다.
| 계층 | 권한 | 금지 (ROE) |
|---|---|---|
| CEO | C레벨 인사(고용/해고), 조직 구조 변경, 전체 진행 판단 | 코드 작성, 직접 워커 지시, 도메인 세부 결정 |
| C-Level | 도메인 정책 수립, 리더 배치 지시, 콘실리에리 활용 토론/작업 | 타 도메인 침범, 직접 워커 지시, 인사권 |
| Leader | 섹션 내 워커 배치, 구현 계획 수립, 워커 결과 검증 | 타 섹션 워커 지시, 정책 수립, 코드 직접 작성 |
| Worker | 코드 작성/수정, 빌드/테스트 실행 | 상위 계층 명령, 타 워커 지시, 정책 결정 |
3.2 ROE (교전규칙) — 도메인 권한
C레벨별 관할 도메인. sections.ts의 cLevel 필드로 코드에 이미 정의되어 있으며, 이를 STRICT 강제한다:
// ROE enforcement — C-Level can only command sections under their domain
interface ROE {
clevelId: CLevel;
allowedSections: string[]; // sections.ts에서 자동 도출
forbiddenActions: string[]; // tier-routing에서 구조적 차단
}
// Example: CTO의 ROE
// allowedSections: ['cto', 'architecture', 'backend', 'frontend', 'qa']
// forbiddenActions: ['budget_decision', 'marketing_campaign', 'hiring_non_tech']
//
// getSectionsForCLevel('cto')로 자동 도출 — 하드코딩 아님
위반 시: STRICT 모드에서 명령 자체가 차단. WARN 모드 폐지.
3.3 SIL (Safety Integrity Level)
모든 에이전트 도구 호출에 위험 등급이 내장된다. 등급에 따라 검증 단계 수가 자동 결정:
| SIL | 위험도 | 검증 | 예시 |
|---|---|---|---|
| SIL-1 | 조회 | 무검증 | Read, Glob, Grep |
| SIL-2 | 분석 | 로그 기록 | WebSearch, WebFetch |
| SIL-3 | 변경 | 단일 검증 (리더 or 자동) | Write, Edit |
| SIL-4 | 파괴/배포 | 이중 검증 (리더 + C레벨) | Bash(rm/deploy), DB 삭제 |
// SIL is derived from the tool itself, not assigned per-task
enum SIL { QUERY = 1, ANALYSIS = 2, MUTATION = 3, DESTRUCTIVE = 4 }
const TOOL_SIL: Record<string, SIL> = {
Read: SIL.QUERY,
Glob: SIL.QUERY,
Grep: SIL.ANALYSIS,
WebSearch: SIL.ANALYSIS,
Write: SIL.MUTATION,
Edit: SIL.MUTATION,
Bash: SIL.DESTRUCTIVE, // default — specific commands can be downgraded
};
// SIL-4 verification: leader.verify() + clevel.verify() both must return true
// SIL-3 verification: leader.verify() only
// SIL-2: log only
// SIL-1: no verification
4. Communications (통신)
4.1 구조화된 출력 = Syscall
계층 간 통신은 스키마 검증된 구조화 출력으로만 이루어진다. 텍스트 파싱(정규식) 금지.
현행 (제거 대상):
C-Level이 텍스트로 "[DELEGATE] backend_dev_1: API 만들어" 출력
→ 정규식으로 파싱 → agentId 추출 → 실패 가능
목표 (구조적 강제):
C-Level → Agent Adapter → 구조화 출력(IR 스키마 준수)
→ 파이프라인이 IR 스키마 검증 → 불일치 시 거부 → 깨질 수 있는 경로 없음
4.2 Agent Adapter — 모델/CLI 교체 대비
파이프라인은 IR 타입만 안다. 어떤 모델로, 어떤 CLI로 IR을 생성하는지는 어댑터 책임.
// Agent Adapter Interface — 모든 모델/CLI가 구현해야 하는 계약
interface AgentAdapter {
// 에이전트를 호출하고 IR 스키마에 맞는 구조화 출력을 반환
invoke<T>(params: AgentInvokeParams<T>): Promise<T>;
}
interface AgentInvokeParams<T> {
agentId: string;
role: string;
systemPrompt: string;
message: string;
outputSchema: JSONSchema; // IR 타입의 JSON 스키마
cwd: string;
tier: AgentTier;
}
// ── 어댑터 구현체 ──
// Claude CLI (현재 사용 중)
class ClaudeCLIAdapter implements AgentAdapter {
// claude -p --json-schema '...' --model sonnet ...
// 또는 claude -p → 텍스트 출력 → 서버 측 스키마 검증
}
// Ollama (Gemma/DeepSeek/Qwen 로컬 모델)
class OllamaAdapter implements AgentAdapter {
// ollama run --format json ...
// 서버 측 스키마 검증
}
// Soldato (Pizza 로컬 모델, 침묵 항해 시 사용)
class SoldatoAdapter implements AgentAdapter {
// soldato run --schema '...' ...
}
// OpenAI Codex
class CodexAdapter implements AgentAdapter {
// codex --json-schema '...' ...
}
// 미래 추가 어댑터
// class QwenAdapter implements AgentAdapter { ... }
// class DeepSeekAdapter implements AgentAdapter { ... }
핵심 원칙:
- 파이프라인 코드에
claude,ollama,codex등의 이름이 직접 등장하지 않는다 - 파이프라인은
adapter.invoke(params)만 호출 - 어댑터 교체 = 환경변수 1개 변경 (
AGENT_ADAPTER=claude-cli | ollama | codex | soldato) - 스키마 검증은 파이프라인 측에서 수행 (어댑터 내부 검증에 의존하지 않음)
// 파이프라인의 Phase 모듈이 어댑터를 사용하는 방식
async function phaseCLevel(directive: CEODirective, adapter: AgentAdapter): Promise<CLevelOrder[]> {
const raw = await adapter.invoke<CLevelOrderOutput>({
agentId: `clevel-${directive.targetCLevel}`,
role: directive.targetCLevel,
systemPrompt: buildCLevelPrompt(directive),
message: JSON.stringify(directive),
outputSchema: CLEVEL_ORDER_SCHEMA, // IR 스키마
cwd: projectDir,
tier: 'clevel',
});
// 파이프라인 측 스키마 재검증 (어댑터를 신뢰하지 않음)
validateIR(raw, CLEVEL_ORDER_SCHEMA); // 실패 시 안돈 발동
return raw.orders;
}
4.3 계층별 출력 스키마
각 계층은 자기 계층의 스키마로만 출력 가능. 타 계층 스키마 출력 불가.
// ── CEO 출력 스키마 ──
// CEO LLM 호출 시 outputSchema로 전달. 이 스키마에 맞는 JSON만 유효 출력.
const CEO_OUTPUT_SCHEMA = {
type: "object",
required: ["action"],
properties: {
action: { type: "string", enum: ["issue_directive", "hire_clevel", "fire_clevel"] },
directives: {
type: "array",
items: {
type: "object",
required: ["targetCLevel", "situation", "mission", "execution", "sustainment", "commandSignal"],
// ... CEODirective 전체 스키마
},
},
hireProposal: {
type: "object",
properties: {
role: { type: "string" },
justification: { type: "string" },
},
},
},
};
// ── C-Level 출력 스키마 ──
const CLEVEL_OUTPUT_SCHEMA = {
type: "object",
required: ["orders"],
properties: {
orders: {
type: "array",
items: {
type: "object",
required: ["section", "mission", "tasks"],
// ... CLevelOrder 전체 스키마
},
},
debateRequest: {
type: "object",
properties: {
topic: { type: "string" },
urgency: { type: "string", enum: ["immediate", "normal", "background"] },
},
},
},
};
// ── Leader 출력 스키마 ──
const LEADER_OUTPUT_SCHEMA = {
type: "object",
required: ["assignments"],
properties: {
assignments: {
type: "array",
items: {
type: "object",
required: ["workerRole", "mission", "targetFiles", "expectedOutput"],
// ... LeaderAssignment 전체 스키마
},
},
},
};
// ── Worker 출력 스키마 ──
// Worker는 코드 실행 도구(Read/Write/Edit/Bash/Glob/Grep)로 작업 후
// 결과를 구조화 출력으로 보고
const WORKER_OUTPUT_SCHEMA = {
type: "object",
required: ["status", "summary", "filesModified"],
properties: {
status: { type: "string", enum: ["success", "failure", "partial"] },
summary: { type: "string" },
filesModified: { type: "array", items: { type: "string" } },
errors: { type: "array", items: { type: "string" } },
},
};
4.3 핸드오프 프로토콜
항공관제 인계 3단계. 계층 간 작업 전달 시 수신 측이 거부할 수 있다.
1. 상위: handoff_request(IR 데이터) → 하위에게 전달
2. 하위: handoff_accept 또는 handoff_reject(사유)
3. 상위: handoff_confirm → 관할 이전 완료
interface HandoffRequest {
fromAgent: string;
toAgent: string;
ir: CEODirective | CLevelOrder | LeaderAssignment;
sil: SIL;
taskStripId: string;
}
interface HandoffResponse {
action: 'accept' | 'reject';
reason?: string; // reject 시 필수
}
// Reject 상한: 2회. 초과 시 자동 에스컬레이션.
// reject 사유: 'out_of_section' | 'resource_exceeded' | 'capability_mismatch'
const MAX_REJECTS_PER_TASK = 2;
거부 시 흐름:
- 1차 거부 → 상위 계층이 재배치 (다른 리더/워커)
- 2차 거부 → 자동 에스컬레이션 (상위 계층의 상위로)
- CEO까지 올라가면 → 회장 에스컬레이션 큐
5. Intelligence (정보)
5.1 보고↑ 채널
현행: 명령↓만 존재. 결과는 agentResults 배열로 수집되지만, 구조화된 보고 채널 없음.
목표: 각 계층이 정형화된 보고서를 상위에 제출. 기존 lifecycle-emitter.ts의 U01~U09 마커와 통합.
Worker → Leader: WorkerResult (U01)
Leader → C-Level: LeaderReport (U02)
C-Level → CEO: CLevelReport (U03)
CEO → Chairman: CEOReport (U04)
보고서는 구조화 출력(IR 스키마) 으로 제출. 텍스트 파싱 아님.
5.2 콘실리에리 정보 수집
콘실리에리는 Intelligence 축의 핵심 자산이다:
- 하향: 에이전트 생성 시
getConsigliereContext(task, role)로 관련 지식 주입 - 상향: 토론 결과, 의사결정 로그를 콘실리에리 DB에 자동 색인
- 수평: C레벨 간 교차 도메인 참조 시 콘실리에리가 관련 문서 제공
C레벨 듀얼트랙에서 콘실리에리의 역할:
C-Level ──┬── [Track A] 토론 (콘실리에리 → 도메인 지식 검색 → 토론 근거 제공)
└── [Track B] 작업 (콘실리에리 → 섹션 컨텍스트 주입 → 리더에게 지시)
5.3 Task Strip (작업 추적표)
항공관제 비행 진행 스트립. 각 task에 메타데이터를 부착하여 파이프라인 어디서든 현재 위치 추적.
interface TaskStrip {
taskId: string;
originMessage: string; // chairman의 원본 요청 ID
currentHolder: string; // 현재 담당 에이전트 ID
tier: AgentTier; // 현재 계층
phase: 'intake' | 'command' | 'handoff' | 'execution' | 'report' | 'review' | 'complete' | 'escalated';
sil: SIL;
handoffCount: number;
rejectCount: number;
elapsedMs: number;
tokensBudget: number;
tokensConsumed: number;
andonHistory: AndonSignal[]; // 이 task에서 발생한 안돈 이력
createdAt: string; // ISO timestamp
}
// Supabase task_strips 테이블 또는 messages 테이블 확장으로 저장
// 실시간 조회: SELECT * FROM task_strips WHERE phase NOT IN ('complete','escalated')
6. IR 타입 정의
컴파일러의 중간 표현(IR) 개념 차용. 각 계층 경계에 타입이 지정된 데이터 구조가 흐른다. 타입 불일치 = 컴파일 에러.
6.1 하향 명령 IR (Command Channel)
// ── Chairman → CEO ──
interface ChairmanDirective {
rawMessage: string;
projectId: string;
channelId: string;
timestamp: string;
}
// ── CEO → C-Level ──
// OPORD 5단계 전부 필수
interface CEODirective {
directiveId: string; // UUID
targetCLevel: CLevel;
situation: string; // 현재 프로젝트 상태 분석
mission: string; // 이번 사이클 달성 목표
execution: {
tasks: TaskSpec[]; // 과업 분해
priority: 'critical' | 'high' | 'normal' | 'low';
};
sustainment: {
tokenBudget: number; // 이 directive에 할당된 토큰
timeoutMs: number; // 최대 허용 시간
memoryLimitMb?: number; // 구획 메모리 상한
};
commandSignal: {
reportTo: 'ceo'; // 항상 CEO에게 보고
escalationCondition: string; // 어떤 조건에서 에스컬레이션
roe: string[]; // 이 directive에 적용되는 ROE
};
}
interface TaskSpec {
taskId: string;
description: string;
section: string; // WHAT: 어떤 섹션의 일인가
sil: SIL; // 위험 등급
// WHO는 여기 없음 — 시스템이 section→leader→worker 매핑
}
// ── C-Level → Leader ──
// mission + execution + sustainment 필수
interface CLevelOrder {
orderId: string;
fromCLevel: CLevel;
section: string;
mission: string;
execution: {
tasks: LeaderTaskSpec[];
constraints: string[]; // 도메인 정책 제약
};
sustainment: {
tokenBudget: number;
timeoutMs: number;
};
}
interface LeaderTaskSpec {
taskId: string;
description: string;
requiredCapability: string; // 'api_dev' | 'ios_dev' | ... — WHAT, not WHO
sil: SIL;
}
// ── Leader → Worker ──
// mission + execution 필수
interface LeaderAssignment {
assignmentId: string;
fromLeader: string;
mission: string;
execution: {
targetFiles: string[]; // 작업 대상 파일
expectedOutput: string; // 기대 결과물 설명
allowedTools: string[]; // harness 퍼미션 매트릭스에서 도출
sil: SIL;
};
}
6.2 상향 보고 IR (Report Channel)
// ── Worker → Leader ──
interface WorkerResult {
assignmentId: string; // LeaderAssignment.assignmentId 참조
status: 'success' | 'failure' | 'partial';
output: string; // 작업 결과 요약
filesModified: string[];
errors: string[];
toolsUsed: string[];
tokensConsumed: number;
elapsedMs: number;
}
// ── Leader → C-Level ──
interface LeaderReport {
orderId: string; // CLevelOrder.orderId 참조
section: string;
summary: string;
completedTasks: string[]; // taskId 목록
failedTasks: {
taskId: string;
reason: string;
recommendation: 'retry' | 'reassign' | 'escalate';
}[];
workerPerformance: {
agentId: string;
tokensUsed: number;
quality: 'good' | 'acceptable' | 'poor';
}[];
tokensConsumed: number;
}
// ── C-Level → CEO ──
interface CLevelReport {
directiveId: string; // CEODirective.directiveId 참조
domain: CLevel;
progress: number; // 0-100
decisionsApplied: string[];
blockers: string[];
debateResults?: string; // consigliere 토론 결과 요약
sectionReports: LeaderReport[]; // 산하 섹션 보고서 집합
recommendations: string[];
tokensConsumed: number;
}
// ── CEO → Chairman ──
interface CEOReport {
projectId: string;
overallProgress: number;
cycle: number; // 몇 번째 워크플로 사이클
directivesIssued: number;
decisionsApplied: string[];
escalations: string[]; // chairman 판단 필요 사항
clevelReports: CLevelReport[];
nextActions: string[];
totalTokens: number;
totalElapsedMs: number;
}
7. 구조화 출력 스키마
4.3절의 계층별 출력 스키마와 6절의 IR 타입이 실제 JSON Schema로 정의된 것. 어댑터가 이 스키마를 모델/CLI에 전달하여 구조화 출력을 강제한다. 스키마 검증은 파이프라인 측에서 수행 — 어댑터 내부 검증에 의존하지 않는다.
7.1 스키마 검증 흐름
Phase 모듈 → adapter.invoke(params, outputSchema)
↓
[어댑터가 모델/CLI 호출]
↓
[모델이 JSON 출력]
↓
adapter → raw JSON 반환
↓
Phase 모듈 → validateIR(raw, schema) ← 파이프라인 측 검증
↓
유효 → IR 객체로 사용
무효 → 안돈 발동 → retry 또는 에스컬레이션
7.2 검증 함수
import Ajv from 'ajv';
const ajv = new Ajv({ allErrors: true });
// 파이프라인 측 IR 검증 — 어댑터를 신뢰하지 않음
function validateIR<T>(raw: unknown, schema: object): T {
const validate = ajv.compile(schema);
if (!validate(raw)) {
throw new IRValidationError(validate.errors);
}
return raw as T;
}
// 검증 실패 시: 안돈 발동 → retry 1회 → 재실패 시 에스컬레이션
// 이 패턴은 A07 구조적 복구와 동일
7.3 핸드오프 스키마
핸드오프 응답도 구조화 출력으로 수신. 수신 측 에이전트가 accept/reject를 IR로 반환.
const HANDOFF_RESPONSE_SCHEMA = {
type: "object",
required: ["action"],
properties: {
action: { type: "string", enum: ["accept", "reject"] },
reason: { type: "string" }, // reject 시 필수
},
};
8. 모듈 분리 — 구획 격리
8.1 Phase 모듈 (Unix 독립 모듈)
현재 모놀리스를 7개 독립 Phase 모듈로 분해한다. 각 모듈은:
- 입력: 하나의 IR 타입
- 출력: 하나의 IR 타입
- 부작용: 정의된 구조화 출력만
- 에러: 안돈 시그널 또는 SCRAM
server/src/pipeline/
├── orchestrator.ts # 배관공 — Phase 간 라우팅만. 비즈니스 로직 0
├── phase-intake.ts # Chairman 메시지 수신 → ChairmanDirective
├── phase-ceo.ts # CEO 분석 → CEODirective[]
├── phase-clevel.ts # C-Level 처리 → CLevelOrder[]
├── phase-leader.ts # Leader 계획 → LeaderAssignment[]
├── phase-worker.ts # Worker 실행 → WorkerResult[]
├── phase-review.ts # 검증/평가 → ReviewResult
├── phase-report.ts # 보고 집계 → CEOReport
├── ir-types.ts # 모든 IR 타입 정의
├── output-schemas.ts # 계층별 구조화 출력 JSON 스키마
├── adapter.ts # AgentAdapter 인터페이스 + 어댑터 팩토리
├── adapters/
│ ├── claude-cli.ts # Claude CLI 어댑터
│ ├── ollama.ts # Ollama 어댑터 (Gemma/DeepSeek/Qwen)
│ └── soldato.ts # Soldato 로컬 모델 어댑터
├── safety.ts # 안돈 + SCRAM + SIL
├── handoff.ts # 핸드오프 프로토콜
└── task-strip.ts # Task Strip 관리
8.2 배관공 (Pipeline Orchestrator)
역할: Phase 출력을 다음 Phase 입력으로 연결. 비즈니스 로직 0.
// orchestrator.ts — pseudo code
async function runPipeline(chairman: ChairmanDirective): Promise<CEOReport> {
// Phase 1: Intake
const intake = await phaseIntake(chairman);
// Phase 2: CEO Analysis
const directives = await phaseCEO(intake);
// Phase 3~5: C-Level → Leader → Worker (순차, ViewHolder)
const clevelResults: CLevelReport[] = [];
for (const directive of directives) {
const orders = await phaseCLevel(directive);
for (const order of orders) {
const assignments = await phaseLeader(order);
for (const assignment of assignments) {
const result = await phaseWorker(assignment); // ViewHolder 슬롯 사용
// 보고↑: Worker → Leader
}
// 보고↑: Leader → C-Level
}
// 보고↑: C-Level → CEO
}
// Phase 6: Review
const review = await phaseReview(clevelResults);
// Phase 7: Report
return phaseReport(review);
}
8.3 구획 격리 (Compartmentalization)
잠수함 구획화. 한 슬롯이 폭주해도 다른 공정에 영향 없음.
interface CompartmentLimits {
maxTokens: number; // 이 구획에 할당된 토큰 상한
maxTimeMs: number; // 시간 상한
maxMemoryMb: number; // 메모리 상한 (프로세스 모니터링)
}
// ViewHolder 슬롯별 구획 상한
const DEFAULT_COMPARTMENT: CompartmentLimits = {
maxTokens: 50000,
maxTimeMs: 300000, // 5분
maxMemoryMb: 256,
};
// 구획 위반 시:
// 1. 토큰 150% 초과 → 안돈 (일시정지)
// 2. 토큰 300% 초과 → SCRAM (강제 종료)
// 3. 시간 초과 → 안돈
// 4. 메모리 초과 → SCRAM (해당 슬롯만 kill, 나머지 무영향)
9. 실행 모델
9.1 순차 실행 + ViewHolder
원칙: 셀프호스팅 환경에서 메모리/CPU 보호. ViewHolder 풀로 CLI 슬롯을 재활용.
ViewHolder Pool (기본 3슬롯)
┌──────────┐ ┌──────────┐ ┌──────────┐
│ slot-0 │ │ slot-1 │ │ slot-2 │
│ idle │ │ idle │ │ idle │
└──────────┘ └──────────┘ └──────────┘
작업 A 도착 → slot-0 bind(A) → 실행 → 완료 → slot-0 release → idle
작업 B 도착 → slot-0 bind(B) → 실행 (재활용)
3개 초과 시 → Queue 대기 → 슬롯 반환 시 자동 할당
- 한 슬롯에서 한 에이전트만 실행
- 에이전트 = CLI가 아니라 주입된 컨텍스트(bind 파라미터)
- 풀 사이즈:
VIEWHOLDER_POOL_SIZE환경변수 (기본 3)
9.2 C레벨 듀얼트랙 (유일한 병렬)
C레벨만 토론과 작업을 콘실리에리를 통해 병렬 수행.
C-Level Agent
├── [Track A: 토론] ── 콘실리에리 ── 다이아몬드 토론 (24/7 상시)
└── [Track B: 작업] ── 콘실리에리 ── 섹션 지시 (요청 도착 시)
두 트랙은 동시 실행. 나머지 모든 것은 순차.
실행 방식: Track A와 Track B는 별도 ViewHolder 슬롯을 점유하지 않는다. 콘실리에리가 자체 프로세스로 운영되며, C레벨은 콘실리에리에게 요청만 전달하고 결과를 수신.
9.3 다이아몬드 토론 실행
다이아몬드 토론은 순차. DAG 노드를 ViewHolder에 하나씩 bind하여 실행.
Root Node → bind(slot-0) → 실행 → 완료
├── Child A → bind(slot-0) → 실행 → 완료 (슬롯 재활용)
├── Child B → bind(slot-0) → 실행 → 완료
└── Child C → bind(slot-0) → 실행 → 완료
Director Node → bind(slot-0) → 수렴 → 완료
10. 안전 체계
10.1 안돈 시그널 (Andon)
도요타 생산라인의 안돈 줄. 수치화된 임계값 초과 시 자동 발동.
interface AndonSignal {
source: string; // 발생 에이전트 ID
taskStripId: string; // 관련 Task Strip
trigger: AndonTrigger;
severity: 'pause' | 'scram';
threshold: number; // 기준값
actual: number; // 실제값
timestamp: string;
}
type AndonTrigger =
| 'token_overrun' // 토큰 예산 초과
| 'consecutive_errors' // 연속 에러
| 'consecutive_timeouts' // 연속 타임아웃
| 'sil_violation' // SIL 등급 위반
| 'memory_overrun' // 메모리 초과
| 'handoff_reject_limit'; // 핸드오프 거부 상한
const ANDON_THRESHOLDS = {
token_overrun_ratio: 1.5, // 예산의 150% → 안돈
consecutive_errors: 3, // 3회 연속 에러 → 안돈
consecutive_timeouts: 2, // 2회 연속 타임아웃 → 안돈
handoff_reject_limit: 2, // 2회 거부 → 안돈 + 에스컬레이션
};
안돈 발동 시 흐름:
- 현재 작업 일시정지 (kill 아님)
- 상위 계층에 AndonSignal 전달
- 상위 계층이 판단:
continue— 임계값 상향 후 재개reassign— 다른 에이전트에게 재배정escalate— 더 상위로 올림abort— 이 task 중단, 보고서에 기록
10.2 SCRAM (긴급정지)
원자력 SCRAM. 안돈보다 심각한 상황에서 파이프라인 전체 즉시 중단.
const SCRAM_THRESHOLDS = {
token_overrun_ratio: 3.0, // 예산의 300% → SCRAM
sil4_unauthorized: true, // SIL-4 이중 검증 없이 실행 시도 → SCRAM
memory_critical_mb: 512, // 시스템 전체 메모리 임계점 → SCRAM
};
SCRAM 발동 시 흐름:
- 모든 ViewHolder 슬롯 즉시 종료
- 진행 중인 모든 Task Strip →
phase: 'escalated'상태 - 현재 상태를 Supabase에 스냅샷 저장 (복구용)
pending_restructure = true설정 (A07 패턴)- 회장에게 SCRAM 발생 보고 (유일한 회장 알림 케이스 — 구조적 복구 불가 상황)
10.3 A07 구조적 복구 통합
기존 A07 패턴(retry → safe state → DB flag → choke point)이 안전 체계의 기본 프레임:
에러 발생
→ retry 1회 (2초 대기)
→ 재실패 시 safe state (변경 없이 안전하게 반환)
→ pending_restructure DB flag 설정
→ 다음 사이클 choke point에서 자동 구조조정
안돈/SCRAM은 이 패턴의 상위 확장:
- 안돈 = 특정 task의 A07 (일시정지 + 상위 판단)
- SCRAM = 전체 파이프라인의 A07 (전체 정지 + 스냅샷 + 복구 대기)
11. 침묵 항해 모드 (Silent Running)
11.1 개요
잠수함의 침묵 항해. 외부 API 불가 시 로컬만으로 핵심 기능 유지.
트리거 조건:
- API 쿼터 소진 (Anthropic rate limit)
- 네트워크 장애
- 회장 수동 전환 (
SILENT_RUNNING=1)
11.2 폴백 경로
정상 모드:
CEO/C-Level/Leader → 기본 어댑터 (ClaudeCLI/Ollama 등 설정에 따름)
Worker → 기본 어댑터
Consigliere → 기본 어댑터 + SQLite
침묵 항해 모드:
CEO/C-Level/Leader → SoldatoAdapter (로컬 Gemma 4, soldato.md 참조)
Worker → SoldatoAdapter
Consigliere → SQLite BM25 캐시만 (임베딩 검색 불가)
전환 = 어댑터 교체. 파이프라인 코드 변경 0.
11.3 성능 저하 명시
침묵 항해 모드에서 축소되는 기능:
| 기능 | 정상 | 침묵 항해 |
|---|---|---|
| C레벨 도메인 분석 | Opus/Sonnet 품질 | Soldato 94% (Pro) ~ 72% (Lite) |
| 콘실리에리 검색 | BM25 + Vector | BM25만 |
| 토론 품질 | 전문가급 | 저하 (모델 성능 의존) |
| SIL-4 검증 | 이중 검증 | 이중 검증 유지 (모델 무관) |
| 핸드오프 프로토콜 | 정상 | 정상 (구조적 — 모델 무관) |
핵심: 구조적 안전 장치(SIL, 핸드오프, 안돈, 타입 검증)는 모델과 무관하게 항상 동작. 침묵 항해에서 저하되는 것은 LLM 판단 품질뿐.
11.4 자동 전환
interface SilentRunningState {
active: boolean;
trigger: 'api_quota' | 'network_failure' | 'manual';
activatedAt: string;
degradedCapabilities: string[];
fallbackModel: string; // 'soldato-pro' | 'soldato-main' | 'soldato-lite'
}
// API 호출 실패 3회 연속 → 자동 전환
// 네트워크 복구 감지 → 자동 복귀 (60초 간격 health check)
const SILENT_RUNNING_TRIGGER_THRESHOLD = 3;
const HEALTH_CHECK_INTERVAL_MS = 60000;
12. 당직 사이클 (Watch Cycle)
12.1 개요
잠수함 3교대 당직 체계. 토큰 예산을 시간대별로 배분하여 24시간 지속 가능한 운용 보장.
12.2 당직 구간
interface WatchPeriod {
name: string;
hours: [number, number]; // [start, end) in 24h
tokenAllocationRatio: number; // 일 예산 중 이 구간 배분 비율
debateThrottlePerHour: number; // 시간당 토론 제한
maxActiveSlots: number; // ViewHolder 최대 슬롯
}
const WATCH_SCHEDULE: WatchPeriod[] = [
{
name: 'peak',
hours: [9, 18], // 09:00-18:00 (회장 활동 시간)
tokenAllocationRatio: 0.6, // 일 예산의 60%
debateThrottlePerHour: 4,
maxActiveSlots: 3,
},
{
name: 'off-peak',
hours: [18, 1], // 18:00-01:00 (저녁)
tokenAllocationRatio: 0.3, // 일 예산의 30%
debateThrottlePerHour: 2,
maxActiveSlots: 2,
},
{
name: 'maintenance',
hours: [1, 9], // 01:00-09:00 (새벽)
tokenAllocationRatio: 0.1, // 일 예산의 10%
debateThrottlePerHour: 1,
maxActiveSlots: 1,
},
];
12.3 예산 관리
interface DailyBudget {
totalTokens: number; // 일 총 예산 (환경변수 DAILY_TOKEN_BUDGET)
consumed: number;
remaining: number;
currentPeriod: WatchPeriod;
periodBudget: number; // 현재 구간에 배분된 예산
periodConsumed: number;
}
// 구간 예산 초과 시:
// - 안돈 발동 (pause) → C-Level 토론 빈도 자동 축소
// - 일 예산 초과 시: SCRAM → 다음날 09:00까지 maintenance 모드
// - 침묵 항해 전환이 가능하면 전환 (Soldato 사용 시 토큰 무관)
12.4 C레벨 듀얼트랙과 당직
peak (09-18):
Track A 토론: 시간당 4회 토론 허용
Track B 작업: 풀 속도
off-peak (18-01):
Track A 토론: 시간당 2회 (심층 토론 위주)
Track B 작업: 긴급 건만
maintenance (01-09):
Track A 토론: 시간당 1회 (유지보수 토론)
Track B 작업: 정지 (예약 작업만)
13. 에스컬레이션
13.1 기존 Level 1~4 통합
현행 에스컬레이션 체계(workflow.md)를 C4I 보고 채널과 통합:
Level 1: Worker 실패 → Leader 개입 (재지시 + 재시도)
└─ WorkerResult(status:'failure') → Leader가 재배정
Level 2: Leader 실패 → C-Level 결정 (다른 섹션 또는 다른 접근)
└─ LeaderReport(failedTasks) → C-Level이 재지시
Level 3: C-Level 실패 → Council 토론 (다중 C-Level 협의)
└─ CLevelReport(blockers) → CEO가 Council 소집
Level 4: Council 실패 → CEO/Chairman 판단
└─ CEO가 해결 불가 → CEOReport(escalations) → Chairman 큐
13.2 핸드오프 거부 에스컬레이션
핸드오프 거부는 안돈과 연동:
1차 거부 → 같은 계층 내 재배치
2차 거부 → 안돈 발동 → 상위 계층 판단
→ 상위가 'reassign' → 다른 섹션으로
→ 상위가 'escalate' → 더 상위로
→ CEO까지 도달 → Chairman 에스컬레이션 큐
13.3 자동 에스컬레이션 매핑
// 에스컬레이션은 보고 채널(구조화 출력 IR)을 통해 구조적으로 흐른다
// 각 level은 lifecycle-emitter 마커와 매핑:
// Level 1: W04 (worker retry) → LH05 (leader intervention)
// Level 2: U02 (leader→clevel report) with status:'failure'
// Level 3: CD01~CD38 (council debate)
// Level 4: U04 (ceo→chairman report) with escalations
14. 현행→목표 대조표
| # | 현행 (As-Is) | 목표 (To-Be) |
|---|---|---|
| 1 | index.ts 모놀리스 핸들러 | 7개 독립 Phase 모듈 + 배관공 |
| 2 | [DELEGATE] 텍스트 파싱 (정규식) | 구조화 출력 (JSON 스키마 검증) + Agent Adapter |
| 3 | WARN 모드 (tier 위반 통과) | STRICT + SIL 등급 (위반 = 차단) |
| 4 | 명령↓만 존재 | 명령↓ + 보고↑ 이중 채널 |
| 5 | 하향 일방 전달 (거부 불가) | 핸드오프 3단계 (요청→수락/거부→확인) |
| 6 | 작업 위치 추적 불가 | Task Strip으로 전 구간 추적 |
| 7 | 하드코딩된 타임아웃 | 안돈(일시정지) + SCRAM(긴급정지) |
| 8 | A07만 safe state | 전 계층 구획 격리 + 자원 상한 |
| 9 | 리더 계층 dead code | 구조적 경유점으로 활성화 (Phase-Leader) |
| 10 | 외부 API 단일 경로 | 침묵 항해 모드 (로컬 Soldato 폴백) |
| 11 | 토큰 총량 제한만 | 당직 사이클 (시간대별 예산 배분) |
| 12 | C레벨 도메인 침범 미감지 | ROE 강제 (sections.ts 기반 자동 도출) |
| 13 | IR 타입 없음 (자유형 텍스트) | OPORD 기반 IR 타입 (TypeScript 타입 안전성) |
| 14 | dispatcher.ts, leader-escalation.ts dead code | 핸드오프/에스컬레이션으로 흡수 또는 삭제 |
부록 A: Lifecycle Emitter 매핑
기존 lifecycle-emitter 체크포인트를 C4I 4대 축에 매핑:
| C4I 축 | 체크포인트 | 설명 |
|---|---|---|
| Command | I01~I03 | Intake — 명령 수신 |
| A01~A09 | CEO Analysis — 명령 해석/분해 | |
| S01~S04 | Spec Issue — 하위 명령서 발행 | |
| D01~D04 | Delegate — 명령 전달 | |
| Control | CH01~CH08 | C-Level Hire — 자산 배치 |
| LH01~LH06 | Leader Hire — 하위 자산 배치 | |
| BD01~BD06 | Build — 검증 | |
| Communications | W01~W17 | Worker Exec — 작전 수행 |
| R01~R17 | Review — 결과 평가 | |
| Intelligence | CD01~CD38 | C-Level Debate — 정보 분석/토론 |
| U01~U09 | Report Up — 정보 상향 보고 |
부록 B: 구현 순서
Phase 1: ir-types.ts + output-schemas.ts (타입/스키마 정의)
Phase 2: adapter.ts + adapters/ (AgentAdapter 인터페이스 + Claude CLI/Ollama/Soldato 어댑터)
Phase 3: safety.ts + handoff.ts + task-strip.ts (안전/통신/추적)
Phase 4: phase-*.ts 7개 모듈 (독립 공정)
Phase 5: orchestrator.ts (배관공)
Phase 6: 기존 index.ts 모놀리스 → orchestrator 호출로 교체
Phase 7: 침묵 항해 + 당직 사이클 (확장 — 어댑터 교체로 자동 적용)
Phase 8: dead code 삭제 (dispatcher.ts, leader-escalation.ts 등)
부록 C: 환경변수
# Pipeline
TIER_ROUTING_STRICT=1 # STRICT 모드 (default: 1, WARN 폐지)
VIEWHOLDER_POOL_SIZE=3 # ViewHolder 슬롯 수
DAILY_TOKEN_BUDGET=1000000 # 일 토큰 예산
# Agent Adapter
AGENT_ADAPTER=claude-cli # claude-cli | ollama | soldato | codex
AGENT_ADAPTER_MODEL=sonnet # 어댑터 내 기본 모델
CLEVEL_ADAPTER=claude-cli # C레벨 전용 어댑터 (별도 지정 가능)
CLEVEL_ADAPTER_MODEL=sonnet # C레벨 모델
# Silent Running
SILENT_RUNNING=0 # 수동 전환 (0=off, 1=on)
SOLDATO_MODEL=soldato-pro # 침묵 항해 시 사용 모델
HEALTH_CHECK_INTERVAL_MS=60000 # API 상태 확인 간격
# Safety
SCRAM_TOKEN_RATIO=3.0 # SCRAM 토큰 임계 비율
SCRAM_MEMORY_MB=512 # SCRAM 메모리 임계값
ANDON_TOKEN_RATIO=1.5 # 안돈 토큰 임계 비율
ANDON_CONSECUTIVE_ERRORS=3 # 안돈 연속 에러 임계
ANDON_CONSECUTIVE_TIMEOUTS=2 # 안돈 연속 타임아웃 임계
# Watch Cycle
WATCH_PEAK_HOURS=9-18 # 피크 시간대
WATCH_OFFPEAK_HOURS=18-1 # 오프피크 시간대
WATCH_PEAK_RATIO=0.6 # 피크 예산 비율
WATCH_OFFPEAK_RATIO=0.3 # 오프피크 예산 비율