fix(sister-agent): trivial tier ghost pipeline + openclaw model override 거부
## Bug 1: trivial tier 가 산출물 없는 유령 파이프라인 생성
planner.ts 의 trivial 케이스가 strategy="direct" + spawn=[] 였음. 그런데
spawn.ts 의 maybeExtractFiles() 는 role !== "junior" 면 파일을 저장하지
않고, manager 의 프롬프트는 "본인이 직접 코드를 짜지 않는다" 로 박혀 있어,
trivial 태스크는 아무도 코드를 안 쓰는 상태로 done 처리됨.
수정: trivial tier 도 single-junior 로 강제. junior 1 명이 무조건 코드를
생성하게 함. 이전 "direct" 전략은 의도적으로 사용 안 함.
재현: "간단한 todo 앱 만들어" → score 10 → tier=trivial → ghost pipeline
검증: smoke-todo-v3 파이프라인이 implement/files/frontend/sprints/SPRINT-AUTO/
index.html (115 줄) 을 실제로 생성함
## Bug 2: openclaw 어댑터가 모델 override 로 OpenClaw 거부됨
LLM 어댑터 리팩터 시 spawn.ts 에서 callLlm 에 model: ROLES[role].primaryModel
을 명시하게 했는데, 그 모델 이름 (gpt-5.4 / glm-5-turbo 등) 이 OpenClaw
agent="main" 의 allowlist 에 없어서 "Model override not allowed" 로 거부됨.
수정: openclaw 어댑터는 --model 플래그를 더 이상 넘기지 않음. OpenClaw 의
자체 라우팅에 모델 선택을 위임. 다른 어댑터 (openai/anthropic/ollama) 는
그대로 req.model 을 honor 함.
검증: smoke-todo-v3 의 narang junior 가 LLM 호출 성공, 실제 HTML 생성
This commit is contained in:
@@ -21,8 +21,13 @@ export class OpenClawAdapter implements LlmAdapter {
|
||||
}
|
||||
|
||||
async infer(req: LlmRequest): Promise<LlmResult> {
|
||||
// Note: we intentionally do NOT pass `--model` to openclaw. OpenClaw has
|
||||
// its own per-agent model allowlist and routing logic, and overriding it
|
||||
// with rails-side role names like `gpt-5.4` / `glm-5-turbo` causes
|
||||
// "Model override not allowed for agent main" errors. Other adapters
|
||||
// (openai/anthropic/ollama) still honor req.model — only this adapter
|
||||
// delegates model selection back to the runtime.
|
||||
const args = ["infer", "model", "run", "--prompt", req.prompt, "--json"];
|
||||
if (req.model) args.push("--model", req.model);
|
||||
|
||||
return new Promise((resolveFn) => {
|
||||
const child = spawn(this.bin, args, {
|
||||
|
||||
@@ -32,13 +32,25 @@ export function planDecomposition(complexity: ComplexityScore): DecompositionPla
|
||||
|
||||
switch (tier) {
|
||||
case "trivial":
|
||||
// Even trivial tasks need a junior to actually produce code. Managers
|
||||
// are planner-only by role definition and maybeExtractFiles() in
|
||||
// spawn.ts only saves files from juniors. Without a junior the
|
||||
// pipeline completes "successfully" with zero output — the classic
|
||||
// ghost-pipeline bug. Spawn 1 junior to guarantee something lands.
|
||||
return {
|
||||
tier,
|
||||
score,
|
||||
strategy: "direct",
|
||||
spawn: [],
|
||||
strategy: "single-junior",
|
||||
spawn: [
|
||||
{
|
||||
role: "junior",
|
||||
count: 1,
|
||||
rationale:
|
||||
"Trivial task still needs one junior to produce actual output. Manager can't write code per role definition.",
|
||||
},
|
||||
],
|
||||
notes: [
|
||||
"Manager handles directly — no team needed for trivial tasks.",
|
||||
"Even trivial tasks spawn one junior so the pipeline actually produces files.",
|
||||
],
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user