20 KiB
서브에이전트 프롬프트
단계마다 에이전트를 하나 띄운다. 아래를 그대로 쓰고 <...> 만 바꾼다.
에이전트를 새로 만들지 않는다. 단계마다 맡을 에이전트가 .claude/agents/ 에 있고,
Agent 도구의 subagent_type 에 그 이름을 준다. 절마다 첫 줄에 적혀 있다.
Agent(subagent_type="record-writer", prompt=<아래 S3 프롬프트>)
에이전트 정의가 그 단계의 「하는 일 · 안 하는 일 · 관문 · 보고」를 이미 적고 있다. 그래서 프롬프트는 이번 런의 입력 경로와 글감을 준다 — 아래 것을 그대로 쓰되, 정의와 어긋나는 지시를 프롬프트로 덮어쓰지 않는다.
모든 프롬프트에 들어가는 넷
- 스킬 이름과 「SKILL.md 를 끝까지 먼저 읽어라」. 요약을 주지 않는다. 요약을 주면 스킬을 안 연다.
- 자기 단계의 입력 경로만. 앞 단계가 무엇을 했는지 설명하지 않는다.
- 관문 명령 원문. 「검사해라」가 아니라 붙여 넣을 수 있는 명령을 준다.
- 스킬 영수증 — SKILL.md 에서 한 줄을 원문 그대로 인용해 돌려보내게 한다.
verify-pipeline-run.py가 그 문자열이 실제 파일 안에 있는지 대조한다.
돌려받는 형식 (모든 단계 공통)
{
"stage": "S3",
"skill": "writing-tech-log-records",
"skillEcho": "<SKILL.md 에서 그대로 옮긴 한 줄>",
"status": "DONE",
"outputs": ["docs/keycloak/tech-log-studio/.../case-x.md"],
"gates": [{"cmd": "node ... check_body.mjs /tmp/studio-body.md", "exit": 0}],
"notes": "<판단한 것과 못 한 것>"
}
skillEcho 를 지어내지 말라고 프롬프트에 적는다. 파일에 없는 문장이면 검사기가 잡는다.
파일을 쓰라고 할 때는 방법을 함께 준다
서브에이전트의 Write 는 「보고는 파일이 아니라 글로 돌려라」는 기본 정책에 막힐 수 있다.
S1 처럼 산출물이 .md 인 단계는 그래서 한 줄을 더한다.
파일을 쓸 때 Write 툴이 막히면 Bash heredoc (`cat > 경로 <<'EOF'`) 을 써라.
이것을 안 적으면 에이전트가 산출물을 만들지 못하고 본문에 통째로 붙여 돌려준다.
S1 — 코드베이스 → SSOT
에이전트: ssot-analyst — subagent_type="ssot-analyst"
너는 Tech Log 파이프라인의 1단계를 맡는다.
먼저 .agents/skills/analyzing-codebase-for-tech-log/SKILL.md 를 끝까지 읽어라.
references/ 아래 문서도 그 스킬이 읽으라는 것을 읽어라. 요약본은 주지 않는다.
대상 저장소: <절대 경로>
쓸 곳: docs/<프로젝트>/
analysis-queue.yaml 이 없으면 이 저장소 하나만 분석한다. 큐가 없다는 이유로 멈추지 마라.
대상 저장소를 고치지 마라. 읽기만 한다.
끝나면 분석 재료를 SSOT 로 합쳐라:
python3 scripts/fold-analysis-into-final.py <프로젝트>
합친 뒤 analysis/ · notes/ · checkpoints/ · state.json · source-index.md 를 지운다.
관문:
python3 scripts/verify-project-layout.py <프로젝트>
error 0 이 될 때까지 고쳐라.
돌려줄 것 (JSON):
stage, skill, skillEcho, status, outputs, gates, notes
skillEcho 는 방금 읽은 SKILL.md 에서 네 작업에 해당하는 규칙 한 줄을 원문 그대로 옮긴 것이다.
지어내지 마라 — 파일에 그 문자열이 있는지 기계가 대조한다.
S2 — SSOT → 분해 계약
에이전트: tree-deriver — subagent_type="tree-deriver"
너는 Tech Log 파이프라인의 2단계를 맡는다.
먼저 .agents/skills/deriving-tech-log-root-tree/SKILL.md 를 끝까지 읽어라.
references/candidate-disposition.md 와 references/decomposition-checklist.md 도 읽어라.
출력 계약은 .agents/skills/writing-tech-log-records/references/tech-log-tree-contract.md 다.
입력: docs/<프로젝트>/final/document.md — 이것 하나다.
analysis/** 를 후보를 찾으려고 열지 마라.
출력: docs/<프로젝트>/tech-log-studio/tech-log-tree.json
검사기가 error 로 요구하는데 스킬 본문이 안 적는 칸 셋을 손으로 채워라:
candidateScope — 후보를 찾은 범위
sourceRepository — 분석한 저장소의 경로·리비전·판단 근거. 모르면 null 로 두고 지어내지 마라
ssotSha256 — build 가 채운다. 그래서 build 를 먼저 돌린다
제외가 0 건인 분해는 선별하지 않은 분해다. 후보마다 처분을 적고, 다시 읽은 것만
dispositionReview: CONFIRMED 로 둬라.
관문:
python3 scripts/build-tech-log-tree.py <프로젝트>
python3 scripts/verify-tech-log-tree.py <프로젝트>
error 0 까지 고쳐라.
돌려줄 것: 위 JSON 형식. skillEcho 포함.
S3 — 글감 → 기록
에이전트: record-writer — subagent_type="record-writer"
너는 Tech Log 파이프라인의 3단계를 맡는다.
먼저 .agents/skills/writing-tech-log-records/SKILL.md 를 끝까지 읽어라.
그 스킬이 가리키는 references/ 중 네 종류에 해당하는 것을 읽어라 —
record-kinds.md · writing-each-kind.md · body-syntax.md · code-tables-diagrams.md ·
explaining.md · ai-tells.md · choosing-a-diagram.md.
**종류가 Setup 이면 본문을 쓰기 전에 `Skill` 도구로 `writing-practitioner-guides` 를 연다.**
명령을 어떤 형태로 쓸지는 그 스킬이 정한다 — 사람이 직접 치는 실습 가이드이지 에이전트가
실행하기 편한 명령이 아니다. **그 스킬을 못 열면 Setup 을 쓰지 말고 그 사실을 돌려줘라.**
안 열고 쓴 Setup 은 검사기를 다 지나면서도 실행이 중간에 끊긴다 — 실제로 그렇게 나갔다.
글감: docs/<프로젝트>/tech-log-studio/tech-log-tree.json 의 <주제> / <종류> / "<제목>"
그 노드가 PROMOTE 이고 dispositionReview 가 CONFIRMED 인지 먼저 확인해라. 아니면 쓰지 마라.
근거: 그 노드의 source 앵커가 가리키는 docs/<프로젝트>/final/document.md 의 절.
인용하는 줄은 SSOT 에서 찾아 대조해라. 기억이나 다른 기록에서 옮겨 적지 마라.
쓸 곳: docs/<프로젝트>/tech-log-studio/<주제>/<종류>/<파일>.md
그림이 필요해 보이면 docs/<프로젝트>/final/assets/ 에 이미 있는지부터 봐라.
없으면 이 단계에서 만들지 말고 notes 에 "그림 필요: <무엇을>" 이라고 적어라. 4단계가 만든다.
관문:
python3 scripts/studio-body.py <기록.md> -o /tmp/studio-body.md
node --experimental-transform-types \
.agents/skills/writing-tech-log-records/scripts/check_body.mjs /tmp/studio-body.md
node .agents/skills/rewriting-technical-prose-naturally/scripts/check_prose.mjs --warn <기록.md>
node .agents/skills/writing-tech-log-records/scripts/check_evidence.mjs <프로젝트> --repo
error 0 까지 고쳐라.
돌려줄 것: 위 JSON 형식. skillEcho 포함.
S3-C1 — initial command analysis
S3가 끝나면 항상 deterministic initial command analysis를 만든다.
python3 scripts/check-command-pedagogy.py <기록.md> --mode <문서 mode> \
-o runs/<프로젝트>/<runId>/stage/S3/command-initial.json
shell/CLI block이 0이면 아래 세 command agent를 부르지 않고 원장의 planner/editor/reviewer를
SKIPPED로 적는다. block은 있지만 finding이 0이면 planner/editor만 SKIPPED다.
S3-C2 — CommandPlan (finding이 있을 때만)
Agent(subagent_type="command-pedagogy-planner", prompt=<아래 command planner 프롬프트>)
너는 command-pedagogy planner다.
먼저 .agents/skills/writing-practitioner-guides/SKILL.md 를 끝까지 읽고
references/command-pedagogy.md 도 읽어라.
기록: <기록.md>
initial command analysis: runs/<프로젝트>/<runId>/stage/S3/command-initial.json
근거: <이 기록의 source가 가리키는 SSOT 절>
분석이 지목한 block만 계획해라. Markdown을 수정하지 마라.
SSOT/evidence에 없는 alias, prerequisite, 성공 결과를 만들지 마라.
compact syntax 자체를 금지하지 말고 문서 모드와 관찰 가능성으로 판단해라.
돌려줄 것: CommandPlan JSON + skillEcho.
skillEcho는 writing-practitioner-guides/SKILL.md에서 원문 한 줄을 그대로 옮긴 것이다.
CommandPlan을 runs/<프로젝트>/<runId>/stage/S3/command-plan.json에 저장한 뒤 frozen analysis와 검증한다.
python3 scripts/validate-command-pedagogy-artifact.py plan \
runs/<프로젝트>/<runId>/stage/S3/command-plan.json \
--analysis runs/<프로젝트>/<runId>/stage/S3/command-initial.json
S3-C3 — bounded command editor (finding이 있을 때만)
Agent(subagent_type="command-pedagogy-editor", prompt=<아래 command editor 프롬프트>)
너는 command-pedagogy editor다.
먼저 .agents/skills/writing-practitioner-guides/SKILL.md 를 끝까지 읽고
references/command-pedagogy.md 도 읽어라.
기록: <기록.md>
initial command analysis: <command-initial.json>
CommandPlan: <command-plan.json>
근거: <이 기록의 source가 가리키는 SSOT 절>
기록 파일을 직접 수정하지 마라. frozen plan의 block_id에 대한 CommandPatchSet JSON만 만들어라.
command block 밖의 산문, 기술 주장, target host/session, file meaning, security boundary를 바꾸지 마라.
돌려줄 것: CommandPatchSet JSON + skillEcho.
CommandPatchSet을 runs/<프로젝트>/<runId>/stage/S3/command-patch-set.json에 저장하고 검증한다.
python3 scripts/validate-command-pedagogy-artifact.py patch \
runs/<프로젝트>/<runId>/stage/S3/command-patch-set.json \
--analysis runs/<프로젝트>/<runId>/stage/S3/command-initial.json
editor 결과는 에이전트가 직접 적용하지 않는다. host orchestrator가 bounded applier를 쓴다.
python3 scripts/apply-command-pedagogy-patch.py \
<기록.md> <command-initial.json> <command-patch-set.json> \
-o /tmp/command-repaired.md
mv /tmp/command-repaired.md <기록.md>
그 다음 S3 관문을 다시 실행하고 S4로 간다.
S4 — 기록 → 그림
에이전트: diagram-maker — subagent_type="diagram-maker"
너는 Tech Log 파이프라인의 4단계를 맡는다.
먼저 두 개를 읽어라:
.agents/skills/technical-visualizer/SKILL.md — 끝까지
.agents/skills/writing-tech-log-records/references/choosing-a-diagram.md
기록: <기록.md>
이 기록을 읽고 무엇을 그릴지 정해라. 세 관문을 지나야 그린다 —
자리가 Case·Concept 인가 / 표로 될 것이 아닌가 / 옆 문단이 이미 말하지 않았는가.
그리고 그림이 주장하는 것을 이 기록 본문이 말하고 있어야 한다. 본문이 안 적은 단계를
그림만으로 넣지 마라.
그림의 근거는 기록이 아니라 기록의 source 앵커가 가리키는 SSOT 절이다:
./scripts/techviz prepare docs/<프로젝트>/final/document.md \
--heading "<그 절 제목>" \
-o docs/<프로젝트>/final/.techviz/<이름>/context.json
--line 은 쓰지 마라.
그림 안의 <text> 는 전부 이름이어야 한다. 문장은 <desc> 와 옆 문단에 둬라.
관문:
./scripts/techviz lint docs/<프로젝트>/final/.techviz/<이름>/spec.json \
--context docs/<프로젝트>/final/.techviz/<이름>/context.json
python3 scripts/check-figure-text.py <프로젝트>
python3 scripts/check-figure-overlap.py <프로젝트>
python3 scripts/preview-figure.py <프로젝트> -o /tmp/figs
마지막 것은 PNG 로 떠서 라벨이 상자를 덮지 않는지 눈으로 봐라. lint 는 그것을 못 잡는다.
기록에 되적어라 — frontmatter assets: 에 key 와 file, 본문에는 마크다운 이미지.
:::evidence 를 저장소 .md 에 쓰지 마라.
돌려줄 것: 위 JSON 형식. skillEcho 포함. 그리지 않기로 했으면 status 를 SKIPPED 로 하고
어느 관문에 걸렸는지 적어라.
S5 — AI 티 제거
에이전트: prose-rewriter — subagent_type="prose-rewriter"
너는 Tech Log 파이프라인의 5단계를 맡는다.
먼저 .agents/skills/rewriting-technical-prose-naturally/SKILL.md 를 끝까지 읽어라.
그 스킬이 "첫 rewrite 전에 읽으라"고 지정한 references 세 개도 읽어라 —
document-skeleton.md · article-shape.md · korean-tech-blog-register.md.
고칠 파일: <기록.md> (제자리에서 고친다)
너의 일은 문체다. 사실을 만들지 마라. 분류가 틀렸거나 근거가 모자란 것은 네 일이 아니다 —
발견하면 고치지 말고 notes 에 적어라.
보호 구간을 건드리지 마라: 수치 · 날짜 · 버전 · 단위 · 코드 · 명령어 · URL · 직접 인용 ·
공식 명칭. 한 글자도 달라지면 안 된다.
관문:
S=.agents/skills/rewriting-technical-prose-naturally/scripts
node $S/check_prose.mjs --warn <기록.md> # error 0 까지
node $S/style_profile.mjs <기록.md>
그리고 문장을 고쳤으니 본문 문법과 인용을 다시 본다:
python3 scripts/studio-body.py <기록.md> -o /tmp/studio-body.md
node --experimental-transform-types \
.agents/skills/writing-tech-log-records/scripts/check_body.mjs /tmp/studio-body.md
node .agents/skills/writing-tech-log-records/scripts/check_evidence.mjs <프로젝트> --repo
수치를 맞추려고 문장을 넣지 마라. 검사기는 표면 패턴만 본다.
돌려줄 것: 위 JSON 형식. skillEcho 포함.
S6 — 일한 사람의 목소리
에이전트: voice-writer — subagent_type="voice-writer"
너는 Tech Log 파이프라인의 6단계를 맡는다.
먼저 .agents/skills/writing-as-the-person-who-did-it/SKILL.md 를 끝까지 읽어라.
references/voice-moves.md 도 읽어라. 그 스킬이 "이것보다 먼저 본다"고 한
../rewriting-technical-prose-naturally/references/article-shape.md 를 먼저 읽어라.
고칠 파일: <기록.md> (제자리에서 고친다)
상류 자료: docs/<프로젝트>/final/document.md · <대상 저장소의 커밋 메시지·주석·README>
찾을 것은 자료에 남아 있는 사람의 흔적이다 — 무엇을 골랐고 무엇과 견주었나,
확인하지 못한 것이 무엇이고 그것이 어느 주장에 걸리나, 처음 생각과 어긋난 자리가 있나.
없는 사람을 만들지 마라. 「처음에는」·「고민 끝에」·「놀랍게도」를 자료 없이 쓰면 지어낸 것이다.
넣은 문장마다 그것이 어느 파일 어느 줄에서 왔는지 댈 수 있어야 한다.
자료에 흔적이 없으면 아무것도 넣지 말고 그렇게 보고해라. 그것도 이 단계를 한 것이다.
관문:
node .agents/skills/writing-as-the-person-who-did-it/scripts/check_voice.mjs <기록.md>
node .agents/skills/rewriting-technical-prose-naturally/scripts/check_prose.mjs --warn <기록.md>
python3 scripts/studio-body.py <기록.md> -o /tmp/studio-body.md
node --experimental-transform-types \
.agents/skills/writing-tech-log-records/scripts/check_body.mjs /tmp/studio-body.md
node .agents/skills/writing-tech-log-records/scripts/check_evidence.mjs <프로젝트> --repo
check_voice.mjs 는 목소리가 모자란지 재지 않는다. 지어낸 목소리를 잡는다.
돌려줄 것: 위 JSON 형식. skillEcho 포함. 흔적이 없었으면 status DONE 에 notes 로 적어라.
R1 — final command analysis + independent command review
S6가 끝나면 final command analysis를 다시 만든다.
python3 scripts/check-command-pedagogy.py <기록.md> --mode <initial과 같은 문서 mode> \
-o runs/<프로젝트>/<runId>/review/command-final.json
initial analysis에 shell block이 있었는데 final이 0이면 멈춘다. final majorFindings가 남아도
멈춘다. final shell/CLI block이 하나라도 있으면 다음 reviewer를 부른다.
Agent(subagent_type="command-pedagogy-reviewer", prompt=<아래 command reviewer 프롬프트>)
너는 final command-pedagogy reviewer다. 파일을 고치지 마라.
먼저 .agents/skills/writing-practitioner-guides/SKILL.md 를 끝까지 읽고
references/command-pedagogy.md 도 읽어라.
최종 기록: <기록.md>
initial command analysis: <command-initial.json>
final command analysis: <command-final.json>
CommandPlan: <있으면 command-plan.json, 없으면 null>
근거: <이 기록의 source가 가리키는 SSOT/evidence>
최종 command가 기술적으로 같은 일을 하면서 사람이 실행·관찰·진단할 수 있는지 독립적으로 판정해라.
직접 수정하지 마라. PASS / FAIL / UNCERTAIN 중 하나만 낸다.
FAIL과 UNCERTAIN은 acceptance를 막는다.
돌려줄 것: reviewer, verdict, findings, notes + skillEcho.
R2 — final technical-evidence review
command/prose/voice 수정이 모두 끝난 뒤 마지막으로 fact reviewer를 부른다. command가 없는 글도 이 검토는 생략하지 않는다.
Agent(subagent_type="fact-reviewer", prompt=<아래 fact reviewer 프롬프트>)
너는 최종 technical-evidence reviewer다. 파일을 고치지 마라.
최종 기록: <기록.md>
SSOT: docs/<프로젝트>/final/document.md
추가 evidence: <tech-log-tree node가 가리키는 증거와 원본 가이드 경로>
모든 command repair, prose rewrite, voice edit가 끝난 이 최종본을 원문과 역대조해라.
수치·단위·경로 결합·미검증→확정 전환·유무 오기·비밀 노출을 본다.
돌려줄 것은 fact-reviewer 계약의 VERDICT: PASS | FAIL 형식이다.
PASS만 S7로 갈 수 있다.
두 결과를 각각 qualityReviews.commandPedagogy.reviewer와
qualityReviews.technicalEvidence에 적은 뒤 S7로 간다.
R3 — schemaVersion 4 artifact / hash receipt
v4 원장은 “호출했다”는 문자열만으로 command lane을 통과시키지 않는다. 아래 JSON artifact를
repository 안의 run 디렉터리에 보존하고 각각의 repo-relative path + sha256을 run.json에 적는다.
command-initial.json→qualityReviews.commandPedagogy.initialAnalysis.artifactcommand-plan.json→ planner가 DONE일 때planner.artifactcommand-patch-set.json→ editor가 DONE일 때editor.artifactcommand-final.json→finalAnalysis.artifactcommand-review.json→ reviewer가 DONE일 때reviewer.artifact
영수증 형식은 다음이다.
{"path":"runs/<프로젝트>/<runId>/review/command-final.json","sha256":"<64 hex>"}
파일을 저장한 뒤 sha256sum <artifact>로 실제 digest를 구한다. planner/editor를 조건상 SKIPPED한
경우 해당 artifact는 null이다. command reviewer를 실행했다면 reviewer 결과 JSON에는
source_sha256을 넣고, run.json의 reviewer sourceSha256에도 최종 기록 파일의 SHA256을
같이 적는다.
sha256sum <기록.md>
sha256sum runs/<프로젝트>/<runId>/stage/S3/command-initial.json
sha256sum runs/<프로젝트>/<runId>/review/command-final.json
fact-reviewer도 같은 최종 기록을 검토했다는 증거로
qualityReviews.technicalEvidence.sourceSha256에 동일한 최종 기록 SHA256을 적는다. 그 뒤에 기록
파일을 한 글자라도 바꾸면 reviewer/fact-review를 다시 실행해야 한다.
schemaVersion 3 원장은 이 artifact/hash 필드가 생기기 전 계약이므로 소급해서 채우지 않는다.
S7 — Studio 저장
에이전트: studio-validator — subagent_type="studio-validator"
너는 Tech Log 파이프라인의 7단계를 맡는다.
먼저 .agents/skills/publishing-tech-log-to-studio/SKILL.md 를 끝까지 읽어라.
references/studio-form-map.md 와 references/playwright-recipes.md 도 읽어라.
넣을 기록: <기록.md>
도구: Playwright MCP (mcp__playwright__browser_*)
저장까지만 한다. 게시 버튼을 누르지 마라. 한 번 게시한 문서는 취소해도 삭제가 409 로 거절된다.
상태 레일 aside[class*="studio-document-status"] 가 25초 안에 안 뜨면 인증이 안 된 것이다.
로그인 화면에 자격증명을 입력하지 말고 거기서 멈추고 사용자에게 알려라.
frontmatter 의 id 와 studio: 가 이미 있으면 그 주소로 가라. 새로 만들지 마라.
그림이 있으면 Asset 을 본문보다 먼저 올려라. 순서를 뒤집으면 미리보기가 본문을 막는다.
관문:
상태 레일의 글자가 저장됨 으로 바뀌는 것을 확인 (최대 30초)
python3 scripts/build-tech-log-tree.py <프로젝트>
python3 scripts/verify-tech-log-tree.py <프로젝트>
저장됨 이 안 뜨면 버튼을 다시 누르지 말고 레일의 글자를 그대로 보고해라.
돌려줄 것: 위 JSON 형식. skillEcho 포함. gates 에 저장 전후 version 을 적어라.