Stage 1 + 2 통합 구현 — 사용자 피드백 반영:
manager / principal / lead / junior 계층 구조 추가.
부장이 복잡도를 판단해서 팀을 동적으로 꾸린다.
Design:
- .plans/design/hierarchy.md — 전체 설계 문서 (점수/tier/plan/escalation)
Prisma schema:
- SubTask (계층 트리 + 역할/모델/state/complexity)
- SubTaskEvent (JSONL 스타일 이벤트 로그)
rails (core):
- src/hierarchy/roles.ts — 4역할 기본 config + 모델 매핑
manager/principal: gpt-5.4 / glm-5.1
lead: gpt-codex-5.3 / glm-5
junior: glm-5-turbo / gpt-5
- src/hierarchy/complexity.ts — 규칙 기반 스코어러 (7 factors, 0-100)
- src/hierarchy/planner.ts — tier → DecompositionPlan (trivial/simple/moderate/complex/massive)
+ concurrency budget 강제
- src/hierarchy/store.ts — Prisma CRUD + tree builder
- src/handoff/http-transport.ts — 실제 HTTP transport (MockTransport 대체)
- src/handoff/build.ts — config + env 기반 transport 빌더
(env RAILS_TRANSPORT_MODE + RAILS_AGENT_{STAGE}_HOST 오버라이드)
- src/server/http.ts — sub-task 엔드포인트 4개 추가
POST /api/sub-tasks
PATCH /api/sub-tasks/:id
POST /api/sub-tasks/:id/events
GET /api/pipelines/:id/sub-tasks (tree view)
sister-agent (new sub-project):
- sister-agent/ — 각 LXC 에 배포될 Node.js 데몬
- src/types.ts, roles.ts, complexity.ts, planner.ts
- src/spawn.ts — executeInvocation: 복잡도 점수 → plan → spawn 트리
simulation mode (현재는 work 를 delay 로 시뮬레이트, LLM 연동은 후속)
- src/rails-client.ts — sub-task / event push
- src/server.ts — POST /invoke 엔드포인트 (port 18801)
LXC 리소스 실측 기반 기본 concurrency:
104/106/107: 8 concurrent sub-agents
105 (narang, build 중): 6
검증: tsc --noEmit ✓ | vitest 105/105 ✓ | rails build ✓ | sister-agent build ✓
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
139 lines
4.3 KiB
Plaintext
139 lines
4.3 KiB
Plaintext
generator client {
|
|
provider = "prisma-client-js"
|
|
}
|
|
|
|
datasource db {
|
|
provider = "mysql"
|
|
url = env("DATABASE_URL")
|
|
}
|
|
|
|
model Pipeline {
|
|
id String @id @db.VarChar(26) // ULID
|
|
projectName String @db.VarChar(255)
|
|
requirements String @db.Text
|
|
currentState String @db.VarChar(50) @default("idle")
|
|
contextJson String @db.LongText
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
transitions StateTransition[]
|
|
actorSpawns ActorSpawn[]
|
|
contracts Contract[]
|
|
escalations Escalation[]
|
|
subTasks SubTask[]
|
|
|
|
@@index([currentState])
|
|
@@index([createdAt])
|
|
@@map("pipelines")
|
|
}
|
|
|
|
model StateTransition {
|
|
id Int @id @default(autoincrement())
|
|
pipelineId String @db.VarChar(26)
|
|
fromState String @db.VarChar(50)
|
|
toState String @db.VarChar(50)
|
|
eventType String @db.VarChar(50)
|
|
eventPayload String @db.LongText
|
|
timestamp DateTime @default(now())
|
|
|
|
pipeline Pipeline @relation(fields: [pipelineId], references: [id], onDelete: Cascade)
|
|
|
|
@@index([pipelineId, timestamp])
|
|
@@index([eventType])
|
|
@@map("state_transitions")
|
|
}
|
|
|
|
model ActorSpawn {
|
|
id Int @id @default(autoincrement())
|
|
pipelineId String @db.VarChar(26)
|
|
actorName String @db.VarChar(100)
|
|
stage String @db.VarChar(50)
|
|
spawnedAt DateTime @default(now())
|
|
exitCode Int?
|
|
exitedAt DateTime?
|
|
resultJson String? @db.LongText
|
|
|
|
pipeline Pipeline @relation(fields: [pipelineId], references: [id], onDelete: Cascade)
|
|
|
|
@@index([pipelineId, spawnedAt])
|
|
@@map("actor_spawns")
|
|
}
|
|
|
|
model Contract {
|
|
id String @id @db.VarChar(26) // ULID
|
|
pipelineId String @db.VarChar(26)
|
|
sprintId String @db.VarChar(100)
|
|
version String @db.VarChar(20) @default("v1")
|
|
bodyJson String @db.LongText
|
|
frozenAt DateTime?
|
|
createdAt DateTime @default(now())
|
|
|
|
pipeline Pipeline @relation(fields: [pipelineId], references: [id], onDelete: Cascade)
|
|
|
|
@@index([pipelineId])
|
|
@@index([sprintId])
|
|
@@map("contracts")
|
|
}
|
|
|
|
model SubTask {
|
|
id String @id @db.VarChar(26)
|
|
pipelineId String @db.VarChar(26)
|
|
parentId String? @db.VarChar(26)
|
|
role String @db.VarChar(30)
|
|
agentName String @db.VarChar(50)
|
|
title String @db.VarChar(500)
|
|
description String @db.Text
|
|
state String @db.VarChar(30) @default("queued")
|
|
complexityScore Int?
|
|
complexityTier String? @db.VarChar(20)
|
|
model String @db.VarChar(50) @default("")
|
|
resultJson String? @db.LongText
|
|
errorReason String? @db.Text
|
|
startedAt DateTime?
|
|
completedAt DateTime?
|
|
createdAt DateTime @default(now())
|
|
|
|
pipeline Pipeline @relation(fields: [pipelineId], references: [id], onDelete: Cascade)
|
|
parent SubTask? @relation("SubTaskHierarchy", fields: [parentId], references: [id], onDelete: NoAction, onUpdate: NoAction)
|
|
children SubTask[] @relation("SubTaskHierarchy")
|
|
events SubTaskEvent[]
|
|
|
|
@@index([pipelineId, parentId])
|
|
@@index([state])
|
|
@@index([agentName, state])
|
|
@@map("sub_tasks")
|
|
}
|
|
|
|
model SubTaskEvent {
|
|
id Int @id @default(autoincrement())
|
|
subTaskId String @db.VarChar(26)
|
|
eventType String @db.VarChar(50)
|
|
payloadJson String @db.LongText
|
|
timestamp DateTime @default(now())
|
|
|
|
subTask SubTask @relation(fields: [subTaskId], references: [id], onDelete: Cascade)
|
|
|
|
@@index([subTaskId, timestamp])
|
|
@@index([eventType])
|
|
@@map("sub_task_events")
|
|
}
|
|
|
|
model Escalation {
|
|
id String @id @db.VarChar(26) // ULID
|
|
pipelineId String @db.VarChar(26)
|
|
reason String @db.VarChar(500)
|
|
errorCategory String @db.VarChar(50)
|
|
stage String @db.VarChar(50) @default("")
|
|
attempts Int @default(0)
|
|
contextSnapshot String @db.LongText
|
|
resolvedAt DateTime?
|
|
resolution String? @db.VarChar(50)
|
|
createdAt DateTime @default(now())
|
|
|
|
pipeline Pipeline @relation(fields: [pipelineId], references: [id], onDelete: Cascade)
|
|
|
|
@@index([pipelineId])
|
|
@@index([createdAt])
|
|
@@map("escalations")
|
|
}
|