feat: 가상화 문서들 추가

This commit is contained in:
DongHyeonka
2026-09-10 08:54:05 +09:00
parent e9f6a93327
commit 43e1aadef0
695 changed files with 153404 additions and 12754 deletions
@@ -0,0 +1,269 @@
{
"schemaVersion": 1,
"runId": "2026-09-08-1426",
"project": "virtualization",
"record": "docs/virtualization/tech-log-studio/cpu-virtualization/concept/concept-kvm-vcpu-to-physical-cpu.md",
"startedAt": "2026-09-08T14:26:02+09:00",
"finishedAt": "2026-09-08T22:22:53+09:00",
"stages": [
{
"id": "S1",
"name": "코드베이스 → SSOT",
"skill": "analyzing-codebase-for-tech-log",
"runBy": "subagent",
"status": "SKIPPED",
"skipReason": "분석할 코드베이스가 없다. 사용자가 밖에서 쓴 문서 한 편을 반입한 프로젝트라 CLAUDE.md 「밖에서 문서를 가져올 때」 1·2 단계로 대신했다 — 원본을 source/ 에 복사하고, frontmatter 만 떼고 절의 heading 단계를 한 칸 내려 final/document.md 로 두었다. 이 글감의 근거는 그 안에 전부 있다.",
"skillEcho": "",
"inputs": [
"docs/virtualization/source/kvm-cpu-virtualization-ssot.md"
],
"outputs": [
"docs/virtualization/final/document.md"
],
"gates": [
{
"cmd": "python3 scripts/verify-project-layout.py virtualization",
"exit": 0
}
],
"notes": "오케스트레이터가 반입했다. 서브에이전트를 띄우지 않았다 — 분석이 아니라 파일 이동이라 판단할 것이 없었다. 반입 시점의 SSOT 는 절 23개(1222줄)였고, S2 가 도는 동안 14:31 에 사용자가 §24~§28 을 더한 판(1640줄)으로 final/document.md 를 덮었다. 지운 문장은 없고 430줄이 붙기만 했다(source/ 와 heading marker 를 뺀 본문을 대조). S2 가 그 판의 heading 단계를 다시 맞췄다(h1=1 · h2=28 · h3=65 · h4=4). source/ 의 사본은 그 시점 이후로 낡았다. SSOT 는 측정 자료가 없는 개념 문서다 — final/evidence/ 는 비어 있고 §20·§27 의 OQ 열둘이 아직 안 돌린 실험이다."
},
{
"id": "S2",
"name": "SSOT → 분해 계약",
"skill": "deriving-tech-log-root-tree",
"runBy": "subagent",
"status": "DONE",
"skipReason": "",
"skillEcho": "**Select what is worth publishing. Do not emit everything the analysis found.**",
"inputs": [
"docs/virtualization/final/document.md"
],
"outputs": [
"docs/virtualization/tech-log-studio/tech-log-tree.json"
],
"gates": [
{
"cmd": "python3 scripts/build-tech-log-tree.py virtualization",
"exit": 0
},
{
"cmd": "python3 scripts/verify-tech-log-tree.py virtualization",
"exit": 0
}
],
"notes": "글감 하나 — topic=cpu-virtualization · concept · slug=kvm-vcpu-to-physical-cpu · source 앵커 23개. 후보 39건 처분: PROMOTE 1 · MERGE_INTO 21 · NEEDS_EVIDENCE 13 · KEEP_IN_SSOT 3 · NEEDS_DECISION 1 · PENDING 0. 남은 warn 2 = Topic 에 노드가 하나뿐(사용자가 정한 제약) · sourceRepository 에 리비전이 없다(고정할 커밋이 없다). assetLedger 는 SVG 가 0장이라 안 썼다 — S4 가 그림을 만들면 그때 써야 한다. 런 끝에 오케스트레이터가 sourceRepository 를 고쳤다 — S2 가 적은 path(source/kvm-cpu-virtualization-ssot.md)는 반입 재료라 지웠고, check_evidence 는 체크아웃이 없는 반입 문서일 때 path 가 그 파일이기를 요구한다. 그래서 path 를 final/document.md 로 옮기고 verified 에 사유를 적었다. 다른 칸은 S2 가 쓴 그대로다."
},
{
"id": "S3",
"name": "글감 → 기록",
"skill": "writing-tech-log-records",
"runBy": "subagent",
"status": "DONE",
"skipReason": "",
"skillEcho": "**코드·표·다이어그램·이미지는 본문에만 들어간다. 본문이 있는 종류는 Case 와 Concept 둘뿐이다.**",
"inputs": [
"docs/virtualization/tech-log-studio/tech-log-tree.json",
"docs/virtualization/final/document.md"
],
"outputs": [
"docs/virtualization/tech-log-studio/cpu-virtualization/concept/concept-kvm-vcpu-to-physical-cpu.md"
],
"gates": [
{
"cmd": "python3 scripts/studio-body.py <기록.md> -o /tmp/studio-body.md",
"exit": 0
},
{
"cmd": "node --experimental-transform-types .agents/skills/writing-tech-log-records/scripts/check_body.mjs /tmp/studio-body.md",
"exit": 0
},
{
"cmd": "node .agents/skills/rewriting-technical-prose-naturally/scripts/check_prose.mjs --warn <기록.md>",
"exit": 0
},
{
"cmd": "node .agents/skills/writing-tech-log-records/scripts/check_evidence.mjs virtualization --repo",
"exit": 0
},
{
"cmd": "python3 scripts/build-tech-log-tree.py virtualization",
"exit": 0
},
{
"cmd": "python3 scripts/verify-tech-log-tree.py virtualization",
"exit": 0
}
],
"notes": "후보 SSOT-02-19-execution-path-as-one-concept 가 PROMOTE·CONFIRMED 인 것을 대조하고 착수했다. frontmatter 의 source 23개는 계약에서 스크립트로 옮겼다. 측정값은 하나도 쓰지 않았다 — 마지막 절이 §28 의 경계와 「이 Host 에서 잰 값이 없다」를 명시한다. 그림 필요: virsh→libvirt→QEMU vCPU thread→/dev/kvm→KVM Core→kvm_intel→VMX→물리 CPU 실행 경로와 KVM_RUN·VM Entry·VM Exit 이 되돌아오는 고리. 근거 절 = #2-전체-구조 · #6-kvm_run과-guest-실행 · #7-vm-entry와-vm-exit · #9-vm-exit-이후-처리. 관계 절은 두지 않았다 — 걸 상대가 아직 없다."
},
{
"id": "S4",
"name": "기록 → 그림",
"skill": "technical-visualizer",
"runBy": "subagent",
"status": "DONE",
"skipReason": "",
"skillEcho": "- Every factual boundary/group, node, and edge must cite document line ranges. Unsupported content must be `assumption: true` with no evidence.",
"inputs": [
"docs/virtualization/tech-log-studio/cpu-virtualization/concept/concept-kvm-vcpu-to-physical-cpu.md",
"docs/virtualization/final/document.md#9-vm-exit-이후-처리"
],
"outputs": [
"docs/virtualization/final/.techviz/vm-exit-handling-cycle/spec.json",
"docs/virtualization/final/.techviz/vm-exit-handling-cycle/context.json",
"docs/virtualization/final/.techviz/vm-exit-handling-cycle/prompt.md",
"docs/virtualization/final/assets/diagrams/vm-exit-handling-cycle/vm-exit-handling-cycle.svg"
],
"gates": [
{
"cmd": "./scripts/techviz lint docs/virtualization/final/.techviz/vm-exit-handling-cycle/spec.json --context .../context.json",
"exit": 0
},
{
"cmd": "python3 scripts/check-figure-text.py virtualization",
"exit": 0
},
{
"cmd": "python3 scripts/check-figure-overlap.py virtualization",
"exit": 0
},
{
"cmd": "python3 scripts/preview-figure.py virtualization -o /tmp/figs",
"exit": 0
},
{
"cmd": "node --experimental-transform-types .agents/skills/writing-tech-log-records/scripts/check_body.mjs /tmp/studio-body.md",
"exit": 0
},
{
"cmd": "python3 scripts/build-tech-log-tree.py virtualization",
"exit": 0
},
{
"cmd": "python3 scripts/verify-tech-log-tree.py virtualization",
"exit": 0
},
{
"cmd": "python3 scripts/verify-project-layout.py virtualization",
"exit": 0
}
],
"notes": "그림 하나 — vm-exit-handling-cycle. 근거는 SSOT §9(final/document.md#9-vm-exit-이후-처리). profile=component-flow, 노드 5·엣지 5·assumption 0. 1차 spec 은 Kernel·Userspace 를 groups 로 그렸다가 check-figure-overlap 이 구역 겹침 15750px² 와 라벨 먹힘 99px² 를 냈다. groups 를 걷어 노드 details 로 내리고 재합류 엣지 라벨을 줄여 통과했다 — 기각 사유는 spec 의 metadata.rationale 에 있다. 기록 frontmatter 의 assets: 와 본문 마크다운 이미지, 계약의 assetLedger·ssot-assets 를 되적었다. §24~§26 의 진단 계층 그림은 두 번째 후보였으나 §25 진단표와 겹쳐 그리지 않았다."
},
{
"id": "S5",
"name": "AI 티 제거",
"skill": "rewriting-technical-prose-naturally",
"runBy": "subagent",
"status": "DONE",
"skipReason": "",
"skillEcho": "### Write Korean words in Korean. Latin script is for identifiers only",
"inputs": [
"docs/virtualization/tech-log-studio/cpu-virtualization/concept/concept-kvm-vcpu-to-physical-cpu.md"
],
"outputs": [
"docs/virtualization/tech-log-studio/cpu-virtualization/concept/concept-kvm-vcpu-to-physical-cpu.md"
],
"gates": [
{
"cmd": "node .agents/skills/rewriting-technical-prose-naturally/scripts/check_prose.mjs --warn <기록.md>",
"exit": 0
},
{
"cmd": "node .agents/skills/rewriting-technical-prose-naturally/scripts/style_profile.mjs <기록.md>",
"exit": 0
},
{
"cmd": "python3 scripts/studio-body.py <기록.md> -o /tmp/studio-body.md",
"exit": 0
},
{
"cmd": "node --experimental-transform-types .agents/skills/writing-tech-log-records/scripts/check_body.mjs /tmp/studio-body.md",
"exit": 0
},
{
"cmd": "node .agents/skills/writing-tech-log-records/scripts/check_evidence.mjs virtualization --repo",
"exit": 0
}
],
"notes": "style_profile 벗어남 4→0. engPerSent 6.45→3.50 · hangulRatio 0.47→0.65 · avgLen 72.5→57.2 · longRatio 0.093→0.008 · connPer100 2.8→8.1. 문장 107→124. 주된 편집은 라틴 문자 정리다 — 식별자·고유명사는 그대로 두고 자리잡은 외래어만 한글로 옮겼다. 코드블록 4개와 frontmatter 는 한 글자도 건드리지 않았다(check_evidence 로 확인). 남긴 것: check_prose 경고 5건(VT·QEMU·AMD·SVM·NUMA 미확장) — 다 풀면 라틴 토큰이 늘어 되레 나빠진다고 판단. 근거가 모자란 문제(이 Host 에서 잰 값이 없다)는 S5 범위가 아니라 계약 쪽 일로 남겼다."
},
{
"id": "S6",
"name": "일한 사람의 목소리",
"skill": "writing-as-the-person-who-did-it",
"runBy": "subagent",
"status": "DONE",
"skipReason": "",
"skillEcho": "2. **확인하지 못한 것을 그 대목에서 말한다** — 끝의 목록이 아니라 그 주장 옆에서",
"inputs": [
"docs/virtualization/tech-log-studio/cpu-virtualization/concept/concept-kvm-vcpu-to-physical-cpu.md",
"docs/virtualization/final/document.md",
"docs/virtualization/tech-log-studio/tech-log-tree.json"
],
"outputs": [
"docs/virtualization/tech-log-studio/cpu-virtualization/concept/concept-kvm-vcpu-to-physical-cpu.md"
],
"gates": [
{
"cmd": "node .agents/skills/writing-as-the-person-who-did-it/scripts/check_voice.mjs <기록.md>",
"exit": 0
},
{
"cmd": "node .agents/skills/rewriting-technical-prose-naturally/scripts/check_prose.mjs --warn <기록.md>",
"exit": 0
},
{
"cmd": "python3 scripts/studio-body.py <기록.md> -o /tmp/studio-body.md",
"exit": 0
},
{
"cmd": "node --experimental-transform-types .agents/skills/writing-tech-log-records/scripts/check_body.mjs /tmp/studio-body.md",
"exit": 0
},
{
"cmd": "node .agents/skills/writing-tech-log-records/scripts/check_evidence.mjs virtualization --repo",
"exit": 0
}
],
"notes": "흔적 있음. 넣은 것은 세 곳이고 모두 상류 자료에서 옮겼다 — (1) vCPU 스레드가 논리 CPU 사이를 옮겨 다닌다는 주장 옆에 이 Host 에서 재지 않았다는 것과 PSR 로 확인한다는 것(§20 OQ-5 · §14.7 · 노드의 missing-verification), (2) 진단표가 운영 서버에 그대로 적용되는지는 구성 확인으로 정해진다는 것(§20 OQ-6), (3) 동시성 실험과 부하 실험을 나눠 도는 이유와 견준 대상(§26 · §17.2 의 문구를 그대로 인용). 안 넣은 것: 오독 기록이 없어 「~로 읽기 쉽다」를 안 썼고, 측정이 없어 「어긋난 자리」가 없었고, 코드 저장소가 없어 남의 말을 옮길 자리가 없었다."
},
{
"id": "S7",
"name": "Studio 저장",
"skill": "publishing-tech-log-to-studio",
"runBy": "subagent",
"status": "DONE",
"skipReason": "",
"skillEcho": "기록 `.md` 하나를 Studio 편집 화면에 넣고 **저장**한다. 거기서 끝난다.",
"inputs": [
"docs/virtualization/tech-log-studio/cpu-virtualization/concept/concept-kvm-vcpu-to-physical-cpu.md",
"docs/virtualization/final/assets/diagrams/vm-exit-handling-cycle/vm-exit-handling-cycle.svg"
],
"outputs": [
"docs/virtualization/tech-log-studio/cpu-virtualization/concept/concept-kvm-vcpu-to-physical-cpu.md",
"docs/virtualization/tech-log-studio/tech-log-tree.json"
],
"gates": [
{
"cmd": "상태 레일이 `저장됨` 으로 바뀌는 것을 확인 (건마다)",
"exit": 0
},
{
"cmd": "넣은 값을 화면에서 되읽어 원문과 대조 (건마다)",
"exit": 0
},
{
"cmd": "python3 scripts/build-tech-log-tree.py virtualization",
"exit": 0
},
{
"cmd": "python3 scripts/verify-tech-log-tree.py virtualization",
"exit": 0
}
],
"notes": "앞서 SKIPPED 로 적었던 것을 사용자가 뒤집어 실제로 돌렸다. Studio 에 이 프로젝트의 주제와 프로젝트가 없어 한 번 BLOCKED 로 멈췄고, 사용자가 만들라고 정한 뒤 주제 `CPU 가상화`(slug cpu-virtualization · id e42456e2-9efd-41ee-b676-df82e90f2f53, 논지 칸에 계약의 readerQuestion 기입)와 프로젝트 `가상화` 를 만들고 이어 갔다. 그림 Asset 을 본문보다 먼저 올려 서버 키 vm-exit-handling-cycle-f8448581 을 받고 studio-body.py --key 로 본문을 변환해 넣었다. 저장 버전 1→2, 상태 `저장됨`. 게시하지 않았다. 저장 뒤 오케스트레이터가 편집 화면을 직접 열어 그림이 실제로 뜨는지 확인했다 — figure 안의 img 가 naturalWidth 1195 × 353 · complete true, [role=alert] 0건. 문서: https://hyeonworks.com/studio/documents/5bcae89b-0873-4a2b-af4a-10e5234c085b/edit"
}
]
}
@@ -0,0 +1,326 @@
{
"schemaVersion": 1,
"runId": "2026-09-08-1958",
"project": "virtualization",
"record": "docs/virtualization/tech-log-studio/cpu-virtualization/question/question-vcpu-contention-under-two-vm-load.md",
"startedAt": "2026-09-08T19:58:51+09:00",
"finishedAt": "2026-09-08T22:22:53+09:00",
"stages": [
{
"id": "S1",
"name": "코드베이스 → SSOT",
"skill": "analyzing-codebase-for-tech-log",
"runBy": "subagent",
"status": "SKIPPED",
"skipReason": "SSOT 가 이미 있고 이 열두 글감의 근거가 그 안에 전부 있다 — §20 의 OQ-1~6 과 §27 의 OQ-7~12. 이 런은 SSOT 를 만들거나 고치지 않는다.",
"skillEcho": "",
"inputs": [
"docs/virtualization/final/document.md"
],
"outputs": [],
"gates": [
{
"cmd": "python3 scripts/verify-project-layout.py virtualization",
"exit": 0
}
],
"notes": "앞 런(2026-09-08-1426)이 반입한 SSOT 를 그대로 쓴다. ssotSha256 이 그 런 이후로 바뀌지 않았다."
},
{
"id": "S2",
"name": "SSOT → 분해 계약",
"skill": "deriving-tech-log-root-tree",
"runBy": "subagent",
"status": "DONE",
"skipReason": "",
"skillEcho": "5. Pick **Questions** from the unresolved section (§11).",
"inputs": [
"docs/virtualization/final/document.md",
"docs/virtualization/tech-log-studio/tech-log-tree.json"
],
"outputs": [
"docs/virtualization/tech-log-studio/tech-log-tree.json"
],
"gates": [
{
"cmd": "python3 scripts/build-tech-log-tree.py virtualization",
"exit": 0
},
{
"cmd": "python3 scripts/verify-tech-log-tree.py virtualization",
"exit": 0
},
{
"cmd": "python3 scripts/verify-project-layout.py virtualization",
"exit": 0
}
],
"notes": "§20 OQ-1~6 과 §27 OQ-7~12 열둘을 question 글감으로 올렸다. 후보 12건을 NEEDS_EVIDENCE → PROMOTE·CONFIRMED 로 재판정하고 사유를 reason 에 적었다 — Question 은 아직 닫히지 않은 판단을 적는 종류라 「측정이 없다」가 올리지 못할 이유가 아니고, 사용자가 그렇게 판단했다. 주제는 cpu-virtualization 하나로 두었다. 글감 13 · 후보 처분 PROMOTE 13 · MERGE_INTO 21 · KEEP_IN_SSOT 3 · NEEDS_DECISION 1 · NEEDS_EVIDENCE 1. 남긴 문제: concept 기록과 그 노드의 relations 가 아직 「OQ 열둘이 NEEDS_EVIDENCE 로 있다」고 적고 있다 — 이번 지시 밖이라 그대로 두었고 뒤에서 고친다."
},
{
"id": "S3",
"name": "글감 → 기록",
"skill": "writing-tech-log-records",
"runBy": "subagent",
"status": "DONE",
"skipReason": "",
"skillEcho": "**코드·표·다이어그램·이미지는 본문에만 들어간다. 본문이 있는 종류는 Case 와 Concept 둘뿐이다.**",
"inputs": [
"docs/virtualization/tech-log-studio/tech-log-tree.json",
"docs/virtualization/final/document.md"
],
"outputs": [
"docs/virtualization/tech-log-studio/cpu-virtualization/question/question-exit-distribution-for-keycloak-workload.md",
"docs/virtualization/tech-log-studio/cpu-virtualization/question/question-host-numa-topology.md",
"docs/virtualization/tech-log-studio/cpu-virtualization/question/question-idle-vcpu-thread-appearance.md",
"docs/virtualization/tech-log-studio/cpu-virtualization/question/question-is-production-on-a-hypervisor.md",
"docs/virtualization/tech-log-studio/cpu-virtualization/question/question-pinning-before-and-after.md",
"docs/virtualization/tech-log-studio/cpu-virtualization/question/question-steal-time-increase-under-two-cpu-bound-vms.md",
"docs/virtualization/tech-log-studio/cpu-virtualization/question/question-throttling-vs-contention.md",
"docs/virtualization/tech-log-studio/cpu-virtualization/question/question-throughput-vs-vcpu-count.md",
"docs/virtualization/tech-log-studio/cpu-virtualization/question/question-vcpu-contention-under-two-vm-load.md",
"docs/virtualization/tech-log-studio/cpu-virtualization/question/question-vcpu-thread-migration-without-pinning.md",
"docs/virtualization/tech-log-studio/cpu-virtualization/question/question-virtualization-layer-saturation-during-refresh.md",
"docs/virtualization/tech-log-studio/cpu-virtualization/question/question-vm-exit-distribution-by-workload.md",
"docs/virtualization/tech-log-studio/cpu-virtualization/concept/concept-kvm-vcpu-to-physical-cpu.md",
"docs/virtualization/tech-log-studio/tech-log-tree.json"
],
"gates": [
{
"cmd": "python3 scripts/studio-body.py <기록.md> -o /tmp/sb-*.md (12건)",
"exit": 0
},
{
"cmd": "node --experimental-transform-types .agents/skills/writing-tech-log-records/scripts/check_body.mjs /tmp/sb-*.md (12건)",
"exit": 0
},
{
"cmd": "node .agents/skills/rewriting-technical-prose-naturally/scripts/check_prose.mjs --warn <기록.md> (12건)",
"exit": 0
},
{
"cmd": "node .agents/skills/writing-tech-log-records/scripts/check_evidence.mjs virtualization --repo",
"exit": 0
},
{
"cmd": "python3 scripts/build-tech-log-tree.py virtualization",
"exit": 0
},
{
"cmd": "python3 scripts/verify-tech-log-tree.py virtualization",
"exit": 0
},
{
"cmd": "python3 scripts/audit-records.py virtualization",
"exit": 0
}
],
"notes": "기록 12건을 서브에이전트 셋에 네 건씩 나눠 동시에 썼다(S3-A OQ-1~4 · S3-B OQ-5~8 · S3-C OQ-9~12). 같은 단계 안의 서로 다른 기록이라 병렬로 돌렸고, 프로젝트 전체를 보는 검사기(build·verify-tree·check_evidence)는 배치가 서로의 반쯤 쓴 상태를 보지 않도록 오케스트레이터가 셋이 끝난 뒤 한 번만 돌렸다. 세 배치 모두 같은 것을 지켰다 — Question 은 평문 칸이라 코드블록·표·그림을 넣지 않고 명령은 인라인 코드로만 썼고, 「사실」에는 SSOT 가 확인했다고 적은 것만 넣고 전제한 것은 「가정」으로 뺐으며, 「다음 검증」 아래에 계약의 decision-criterion 을 「닫는 조건」 한 줄로 붙였다. 이 Host 에서 잰 값은 하나도 만들지 않았다. host-numa-topology 는 SSOT 에 NUMA 확인 명령이 없어 명령을 짓지 않았다. 끝에 손질 한 건을 더 돌렸다(S3-T) — concept 기록에 `## 관계` 절이 없었다. question 열둘은 모두 concept 를 가리키는데 반대 방향이 비어 있었다. 스킬을 읽고 열둘을 다 걸지 않고 축마다 허브 하나씩 넷 + 아무도 가리키지 않아 고립되는 둘, 모두 여섯을 걸었다(그 여섯에서 나머지 여섯에 모두 닿는 것을 대조했다). 계약의 concept 노드 relations 와 missing-verification 의 마지막 문장도 「candidates 에 NEEDS_EVIDENCE 로 남아 있다」에서 사실에 맞게 고쳤다. skillEcho(S3-T): 5. **관계 연결** — Decision은 근거가 **1개 이상** 없으면 게시가 거절된다. 런 끝에 오케스트레이터가 평문 칸의 백틱 266개를 지웠다. Question 의 사실·가정·미지수·제약·선택지·다음 검증은 평문으로 렌더링되어 백틱이 글자 그대로 보이는데, S3 프롬프트가 「명령어는 인라인 코드로 쓴다」고 잘못 지시해 audit-records.py 가 「평문 칸에 마크업」 50건을 냈다. 다른 프로젝트는 전부 0건이었다. 백틱만 지웠고 명령 문자열은 그대로다. 지운 뒤 audit-records 0건 · 기록 12건의 check_body·check_prose·check_voice·check_evidence 전부 종료 코드 0."
},
{
"id": "S4",
"name": "기록 → 그림",
"skill": "technical-visualizer",
"runBy": "subagent",
"status": "SKIPPED",
"skipReason": "그릴 자리가 없다. choosing-a-diagram 의 첫 관문이 「자리가 Case·Concept 인가」인데 이번 런의 기록 열둘은 전부 Question 이고, Question 의 칸은 평문으로 렌더링되어 코드·표·다이어그램·이미지가 들어가지 않는다. 그림이 필요하면 Case 나 Concept 에 담고 관계로 가리킨다.",
"skillEcho": "",
"inputs": [],
"outputs": [],
"gates": [],
"notes": "앞 런이 만든 vm-exit-handling-cycle 은 concept 기록이 그대로 쓰고 있고 이번에 건드리지 않았다."
},
{
"id": "S5",
"name": "AI 티 제거",
"skill": "rewriting-technical-prose-naturally",
"runBy": "subagent",
"status": "DONE",
"skipReason": "",
"skillEcho": "**Four buckets. Only the first stays in Latin script.**",
"inputs": [
"docs/virtualization/tech-log-studio/cpu-virtualization/question/question-exit-distribution-for-keycloak-workload.md",
"docs/virtualization/tech-log-studio/cpu-virtualization/question/question-host-numa-topology.md",
"docs/virtualization/tech-log-studio/cpu-virtualization/question/question-idle-vcpu-thread-appearance.md",
"docs/virtualization/tech-log-studio/cpu-virtualization/question/question-is-production-on-a-hypervisor.md",
"docs/virtualization/tech-log-studio/cpu-virtualization/question/question-pinning-before-and-after.md",
"docs/virtualization/tech-log-studio/cpu-virtualization/question/question-steal-time-increase-under-two-cpu-bound-vms.md",
"docs/virtualization/tech-log-studio/cpu-virtualization/question/question-throttling-vs-contention.md",
"docs/virtualization/tech-log-studio/cpu-virtualization/question/question-throughput-vs-vcpu-count.md",
"docs/virtualization/tech-log-studio/cpu-virtualization/question/question-vcpu-contention-under-two-vm-load.md",
"docs/virtualization/tech-log-studio/cpu-virtualization/question/question-vcpu-thread-migration-without-pinning.md",
"docs/virtualization/tech-log-studio/cpu-virtualization/question/question-virtualization-layer-saturation-during-refresh.md",
"docs/virtualization/tech-log-studio/cpu-virtualization/question/question-vm-exit-distribution-by-workload.md"
],
"outputs": [
"docs/virtualization/tech-log-studio/cpu-virtualization/question/question-exit-distribution-for-keycloak-workload.md",
"docs/virtualization/tech-log-studio/cpu-virtualization/question/question-host-numa-topology.md",
"docs/virtualization/tech-log-studio/cpu-virtualization/question/question-idle-vcpu-thread-appearance.md",
"docs/virtualization/tech-log-studio/cpu-virtualization/question/question-is-production-on-a-hypervisor.md",
"docs/virtualization/tech-log-studio/cpu-virtualization/question/question-pinning-before-and-after.md",
"docs/virtualization/tech-log-studio/cpu-virtualization/question/question-steal-time-increase-under-two-cpu-bound-vms.md",
"docs/virtualization/tech-log-studio/cpu-virtualization/question/question-throttling-vs-contention.md",
"docs/virtualization/tech-log-studio/cpu-virtualization/question/question-throughput-vs-vcpu-count.md",
"docs/virtualization/tech-log-studio/cpu-virtualization/question/question-vcpu-contention-under-two-vm-load.md",
"docs/virtualization/tech-log-studio/cpu-virtualization/question/question-vcpu-thread-migration-without-pinning.md",
"docs/virtualization/tech-log-studio/cpu-virtualization/question/question-virtualization-layer-saturation-during-refresh.md",
"docs/virtualization/tech-log-studio/cpu-virtualization/question/question-vm-exit-distribution-by-workload.md",
"docs/virtualization/tech-log-studio/tech-log-tree.json"
],
"gates": [
{
"cmd": "node .agents/skills/rewriting-technical-prose-naturally/scripts/check_prose.mjs --warn <기록.md> (12건)",
"exit": 0
},
{
"cmd": "node .agents/skills/rewriting-technical-prose-naturally/scripts/style_profile.mjs <기록.md> (12건)",
"exit": 0
},
{
"cmd": "python3 scripts/studio-body.py <기록.md> -o /tmp/s5*.md (12건)",
"exit": 0
},
{
"cmd": "node --experimental-transform-types .agents/skills/writing-tech-log-records/scripts/check_body.mjs /tmp/s5*.md (12건)",
"exit": 0
},
{
"cmd": "node .agents/skills/writing-tech-log-records/scripts/check_evidence.mjs virtualization --repo",
"exit": 0
},
{
"cmd": "python3 scripts/build-tech-log-tree.py virtualization",
"exit": 0
},
{
"cmd": "python3 scripts/verify-tech-log-tree.py virtualization",
"exit": 0
}
],
"notes": "배치 셋(S5-A OQ-1~4 · S5-B OQ-5~8 · S5-C OQ-9~12)을 병렬로 돌린 뒤 통합 패스(S5-U) 한 건을 더 돌렸다. 배치 셋이 같은 말을 서로 다르게 옮겨서다 — 12건에 Host 163 / 호스트 46, Guest 67 / 게스트 9 로 갈렸는데 같은 주제의 concept 기록은 호스트 51 / Host 0 이었다. 통합 패스가 concept 를 기준 register 로 삼아 맞췄고, 제목 10건도 frontmatter·h1·계약 노드 title·다른 기록의 관계 참조 네 곳을 동시에 고쳤다. 라틴으로 남긴 것: steal time · pinning · VM Exit · VMX · KVM · QEMU · cgroup · NUMA · CPU-bound 같은 규격·제품·지표 이름과 §25 진단표·§27 측정 항목처럼 SSOT 원문을 전재한 줄. S5-B 가 올린 인용 결함도 이때 고쳤다 — question-steal-time 의 「사실」이 §13 을 옮기며 「가상화 환경에서」를 빠뜨렸던 것을 SSOT 638행과 대조해 되살렸다. style_profile 은 engPerSent 가 몇 편에서 기준 밖으로 남는다 — frontmatter 의 source 앵커와 SSOT 전재 목록이 분자에 들어가는 구조 때문이라 수치를 맞추려고 문장을 넣지 않았다."
},
{
"id": "S6",
"name": "일한 사람의 목소리",
"skill": "writing-as-the-person-who-did-it",
"runBy": "subagent",
"status": "DONE",
"skipReason": "",
"skillEcho": "고치는 방법은 하나뿐이다. **자료에 남아 있는 사람의 흔적을 찾아서 제자리에 놓는다.**",
"inputs": [
"docs/virtualization/tech-log-studio/cpu-virtualization/question/question-exit-distribution-for-keycloak-workload.md",
"docs/virtualization/tech-log-studio/cpu-virtualization/question/question-host-numa-topology.md",
"docs/virtualization/tech-log-studio/cpu-virtualization/question/question-idle-vcpu-thread-appearance.md",
"docs/virtualization/tech-log-studio/cpu-virtualization/question/question-is-production-on-a-hypervisor.md",
"docs/virtualization/tech-log-studio/cpu-virtualization/question/question-pinning-before-and-after.md",
"docs/virtualization/tech-log-studio/cpu-virtualization/question/question-steal-time-increase-under-two-cpu-bound-vms.md",
"docs/virtualization/tech-log-studio/cpu-virtualization/question/question-throttling-vs-contention.md",
"docs/virtualization/tech-log-studio/cpu-virtualization/question/question-throughput-vs-vcpu-count.md",
"docs/virtualization/tech-log-studio/cpu-virtualization/question/question-vcpu-contention-under-two-vm-load.md",
"docs/virtualization/tech-log-studio/cpu-virtualization/question/question-vcpu-thread-migration-without-pinning.md",
"docs/virtualization/tech-log-studio/cpu-virtualization/question/question-virtualization-layer-saturation-during-refresh.md",
"docs/virtualization/tech-log-studio/cpu-virtualization/question/question-vm-exit-distribution-by-workload.md",
"docs/virtualization/final/document.md",
"docs/virtualization/tech-log-studio/tech-log-tree.json"
],
"outputs": [
"docs/virtualization/tech-log-studio/cpu-virtualization/question/question-exit-distribution-for-keycloak-workload.md",
"docs/virtualization/tech-log-studio/cpu-virtualization/question/question-host-numa-topology.md",
"docs/virtualization/tech-log-studio/cpu-virtualization/question/question-idle-vcpu-thread-appearance.md",
"docs/virtualization/tech-log-studio/cpu-virtualization/question/question-is-production-on-a-hypervisor.md",
"docs/virtualization/tech-log-studio/cpu-virtualization/question/question-pinning-before-and-after.md",
"docs/virtualization/tech-log-studio/cpu-virtualization/question/question-steal-time-increase-under-two-cpu-bound-vms.md",
"docs/virtualization/tech-log-studio/cpu-virtualization/question/question-throttling-vs-contention.md",
"docs/virtualization/tech-log-studio/cpu-virtualization/question/question-throughput-vs-vcpu-count.md",
"docs/virtualization/tech-log-studio/cpu-virtualization/question/question-vcpu-contention-under-two-vm-load.md",
"docs/virtualization/tech-log-studio/cpu-virtualization/question/question-vcpu-thread-migration-without-pinning.md",
"docs/virtualization/tech-log-studio/cpu-virtualization/question/question-virtualization-layer-saturation-during-refresh.md",
"docs/virtualization/tech-log-studio/cpu-virtualization/question/question-vm-exit-distribution-by-workload.md"
],
"gates": [
{
"cmd": "node .agents/skills/writing-as-the-person-who-did-it/scripts/check_voice.mjs <기록.md> (12건)",
"exit": 0
},
{
"cmd": "node .agents/skills/rewriting-technical-prose-naturally/scripts/check_prose.mjs --warn <기록.md> (12건)",
"exit": 0
},
{
"cmd": "python3 scripts/studio-body.py <기록.md> -o /tmp/s6*.md (12건)",
"exit": 0
},
{
"cmd": "node --experimental-transform-types .agents/skills/writing-tech-log-records/scripts/check_body.mjs /tmp/s6*.md (12건)",
"exit": 0
}
],
"notes": "배치 셋을 병렬로 돌렸다. 흔적은 두 곳에만 있었다 — 계약 candidates 의 reason(사람이 처분을 뒤집으며 적은 사유)과 SSOT 가 스스로 못박은 문장. 셋이 합해 20문장 남짓을 넣었고 문장마다 출처 절·행을 댔다. 안 넣은 것: 실행 로그·커밋·이 Host 측정값이 없어 「예상과 어긋난 자리」가 없었고, 누가 실제로 틀리게 읽었다는 기록이 없어 「독자 쪽을 보는 문장」도 지어내지 않았다. 「NEEDS_EVIDENCE 에서 PROMOTE 로 재판정했다」는 열둘 모두에 있었지만 같은 문장을 열둘에 넣으면 그것이 또 다른 틀이 되어 구체가 다른 넷에만 넣었다."
},
{
"id": "S7",
"name": "Studio 저장",
"skill": "publishing-tech-log-to-studio",
"runBy": "subagent",
"status": "DONE",
"skipReason": "",
"skillEcho": "기록 `.md` 하나를 Studio 편집 화면에 넣고 **저장**한다. 거기서 끝난다.",
"inputs": [
"docs/virtualization/tech-log-studio/cpu-virtualization/question/question-exit-distribution-for-keycloak-workload.md",
"docs/virtualization/tech-log-studio/cpu-virtualization/question/question-host-numa-topology.md",
"docs/virtualization/tech-log-studio/cpu-virtualization/question/question-idle-vcpu-thread-appearance.md",
"docs/virtualization/tech-log-studio/cpu-virtualization/question/question-is-production-on-a-hypervisor.md",
"docs/virtualization/tech-log-studio/cpu-virtualization/question/question-pinning-before-and-after.md",
"docs/virtualization/tech-log-studio/cpu-virtualization/question/question-steal-time-increase-under-two-cpu-bound-vms.md",
"docs/virtualization/tech-log-studio/cpu-virtualization/question/question-throttling-vs-contention.md",
"docs/virtualization/tech-log-studio/cpu-virtualization/question/question-throughput-vs-vcpu-count.md",
"docs/virtualization/tech-log-studio/cpu-virtualization/question/question-vcpu-contention-under-two-vm-load.md",
"docs/virtualization/tech-log-studio/cpu-virtualization/question/question-vcpu-thread-migration-without-pinning.md",
"docs/virtualization/tech-log-studio/cpu-virtualization/question/question-virtualization-layer-saturation-during-refresh.md",
"docs/virtualization/tech-log-studio/cpu-virtualization/question/question-vm-exit-distribution-by-workload.md"
],
"outputs": [
"docs/virtualization/tech-log-studio/cpu-virtualization/question/question-exit-distribution-for-keycloak-workload.md",
"docs/virtualization/tech-log-studio/cpu-virtualization/question/question-host-numa-topology.md",
"docs/virtualization/tech-log-studio/cpu-virtualization/question/question-idle-vcpu-thread-appearance.md",
"docs/virtualization/tech-log-studio/cpu-virtualization/question/question-is-production-on-a-hypervisor.md",
"docs/virtualization/tech-log-studio/cpu-virtualization/question/question-pinning-before-and-after.md",
"docs/virtualization/tech-log-studio/cpu-virtualization/question/question-steal-time-increase-under-two-cpu-bound-vms.md",
"docs/virtualization/tech-log-studio/cpu-virtualization/question/question-throttling-vs-contention.md",
"docs/virtualization/tech-log-studio/cpu-virtualization/question/question-throughput-vs-vcpu-count.md",
"docs/virtualization/tech-log-studio/cpu-virtualization/question/question-vcpu-contention-under-two-vm-load.md",
"docs/virtualization/tech-log-studio/cpu-virtualization/question/question-vcpu-thread-migration-without-pinning.md",
"docs/virtualization/tech-log-studio/cpu-virtualization/question/question-virtualization-layer-saturation-during-refresh.md",
"docs/virtualization/tech-log-studio/cpu-virtualization/question/question-vm-exit-distribution-by-workload.md",
"docs/virtualization/tech-log-studio/tech-log-tree.json"
],
"gates": [
{
"cmd": "상태 레일이 `저장됨` 으로 바뀌는 것을 확인 (건마다)",
"exit": 0
},
{
"cmd": "넣은 값을 화면에서 되읽어 원문과 대조 (건마다)",
"exit": 0
},
{
"cmd": "python3 scripts/build-tech-log-tree.py virtualization",
"exit": 0
},
{
"cmd": "python3 scripts/verify-tech-log-tree.py virtualization",
"exit": 0
},
{
"cmd": "node .agents/skills/writing-tech-log-records/scripts/check_evidence.mjs virtualization --repo",
"exit": 0
},
{
"cmd": "python3 scripts/audit-records.py virtualization",
"exit": 0
}
],
"notes": "앞서 SKIPPED 로 적었던 것을 사용자가 뒤집어 실제로 돌렸다. Playwright 는 브라우저 하나를 공유하므로 병렬로 못 돌린다 — 네 건씩 세 배치를 순차로 돌렸다. 열두 건 모두 저장 버전 1→2, 상태 `저장됨`. 게시하지 않았고 관계는 비웠다(관계 셀렉트의 후보가 게시된 기록뿐인데 이 프로젝트에는 없다). 화면 라벨이 계약 이름과 셋 달랐다 — `## 사실`→`확인한 사실`, `## 미지수`→`남은 미지수`, `## 선택지`→`검토한 선택지`. `닫는 조건` 칸은 화면에 없어 `다음 검증` 값의 마지막 줄로 넣었다. 평문 렌더라 Studio 에 넣는 값에서만 백틱을 뺐다(명령 문자열은 그대로, 저장소 .md 는 무변경). 마지막 배치가 앞 여덟 건의 선택지 제목 표기를 읽어 대조했다 — 27개 행 전부 일치. 다만 `제외` 표시의 자리가 배치마다 다른데(앞 여덟은 앞, 뒤 넷은 뒤) 이것은 저장소 .md 원문의 차이다."
}
]
}
@@ -0,0 +1,290 @@
{
"schemaVersion": 1,
"runId": "2026-09-09-1052",
"project": "virtualization",
"record": "docs/virtualization/tech-log-studio/memory-virtualization/concept/concept-guest-memory-address-translation.md",
"startedAt": "2026-09-09T10:52:29+09:00",
"finishedAt": "2026-09-09T16:32:05+09:00",
"stages": [
{
"id": "S1",
"name": "코드베이스 → SSOT",
"skill": "analyzing-codebase-for-tech-log",
"runBy": "subagent",
"status": "SKIPPED",
"skipReason": "분석할 코드베이스가 없다. 사용자가 밖에서 쓴 SSOT 세 편(메모리·네트워크·스토리지)을 반입하는 일이라 CLAUDE.md 「밖에서 문서를 가져올 때」 1·2 단계로 대신했다 — 원본을 source/ 에 복사하고, frontmatter 를 떼고 heading 단계를 한 칸 내리고 절 번호만 이 문서의 번호로 옮겨 final/document.md 의 제2·3·4부로 붙인 뒤, heading 이 아닌 줄이 원본과 한 줄도 다르지 않은 것을 대조하고 source/ 를 지웠다. 이 런의 글감 근거는 그 안에 전부 있다.",
"skillEcho": "",
"inputs": [
"docs/virtualization/source/kvm-memory-virtualization-ssot.md",
"docs/virtualization/source/kvm-network-virtualization-ssot.md",
"docs/virtualization/source/kvm-storage-virtualization-ssot.md"
],
"outputs": [
"docs/virtualization/final/document.md",
"docs/virtualization/README.md"
],
"gates": [
{
"cmd": "python3 scripts/verify-project-layout.py virtualization",
"exit": 0
}
],
"notes": "오케스트레이터가 반입했다. 서브에이전트를 띄우지 않았다 — 분석이 아니라 파일 병합이라 판단할 것이 없었다. SSOT 는 절 28개(1640줄) → 절 177개(7719줄). 제2부 §29~§88(원본 절 1~60) · 제3부 §89~§126(원본 절 1~38) · 제4부 §127~§177(원본 절 0~50). §1 의 「이 문서에서는 CPU 가상화만 다룬다 / 네트워크·메모리·스토리지는 별도 범위」 선언이 병합으로 거짓이 되어 그 문단만 고쳤다 — 제1부가 CPU 만 다루고 나머지 셋은 제2·3·4부에 있다고, 범위 밖은 PCIe/VFIO/IOMMU 와 K3s 상세 둘뿐이라고. 대조 결과: 제2부 1765줄 · 제3부 1112줄 · 제4부 1390줄이 원본과 동일. h2 절 슬러그 177개 중복 없음. 남은 warn 1 = SSOT 가 바뀐 뒤 vm-exit-handling-cycle 그림을 다시 보지 않았다(그 그림의 근거 §9 는 이번에 안 바뀌었다)."
},
{
"id": "S2",
"name": "SSOT → 분해 계약",
"skill": "deriving-tech-log-root-tree",
"runBy": "subagent",
"status": "DONE",
"skipReason": "",
"skillEcho": "8. Group `PROMOTE` candidates into Topics. Write one reader question per Topic.",
"inputs": [
"docs/virtualization/final/document.md",
"docs/virtualization/tech-log-studio/tech-log-tree.json"
],
"outputs": [
"docs/virtualization/tech-log-studio/tech-log-tree.json"
],
"gates": [
{
"cmd": "python3 scripts/build-tech-log-tree.py virtualization",
"exit": 0
},
{
"cmd": "python3 scripts/verify-tech-log-tree.py virtualization",
"exit": 0
}
],
"notes": "서브에이전트 셋을 차례로 띄웠다(S2-A 제2부 메모리 · S2-B 제3부 네트워크 · S2-C 제4부 스토리지). 같은 계약 파일 하나를 고치므로 병렬로 돌리지 않았고, 각 에이전트는 앞선 부의 주제·후보를 바이트 단위로 보존한 것을 대조하고 끝냈다. 결과: 주제 1→4 · 글감 13→57 · 후보 39→213. 부별 처분 — 제2부 PROMOTE 20 / MERGE_INTO 55 / KEEP_IN_SSOT 2, 제3부 PROMOTE 10 / MERGE_INTO 35 / KEEP_IN_SSOT 2 / NEEDS_EVIDENCE 1, 제4부 PROMOTE 14 / MERGE_INTO 33 / KEEP_IN_SSOT 1 / NEEDS_DECISION 1. candidateScope.sections 27→176. Case 는 세 부 모두 0 이다 — 이 Host 에서 잰 값이 SSOT 어디에도 없어 Case 를 만들 근거가 없고, 각 부의 OPEN QUESTION 을 그대로 question 글감으로 올렸다(제1부가 세운 기준과 같다). 개념을 몇 편으로 나눌지는 부마다 갈렸고 근거는 SSOT 안에 있다 — 제1부 §19 와 제3부 §121 이 「하나의 CONCEPT 로 관리한다」고 적어 각각 한 편, 그런 지시가 없는 제2부는 여섯 편 제4부는 네 편으로 나눴다. 중복 물음은 MERGE_INTO 로 걷었다 — 제2부 OQ-1·OQ-10 은 제1부 question:host-numa-topology 가 이미 묻고, 제4부 OQ-2 는 OQ-3 과 같은 qemu-img info 한 번으로 닫힌다. 남은 warn 1 = sourceRepository 에 리비전이 없다(코드 저장소가 아니라 반입 문서라 null 로 두었고 verified 에 사유가 있다)."
},
{
"id": "S3",
"name": "글감 → 기록",
"skill": "writing-tech-log-records",
"runBy": "subagent",
"status": "DONE",
"skipReason": "",
"skillEcho": "**코드·표·다이어그램·이미지는 본문에만 들어간다. 본문이 있는 종류는 Case 와 Concept 둘뿐이다.**",
"inputs": [
"docs/virtualization/tech-log-studio/tech-log-tree.json",
"docs/virtualization/final/document.md"
],
"outputs": [
"docs/virtualization/tech-log-studio/tech-log-tree.json"
],
"gates": [
{
"cmd": "python3 scripts/studio-body.py <기록.md> -o /tmp/sb-<slug>.md (44건)",
"exit": 0
},
{
"cmd": "node --experimental-transform-types .agents/skills/writing-tech-log-records/scripts/check_body.mjs /tmp/sb-<slug>.md (44건)",
"exit": 0
},
{
"cmd": "node .agents/skills/rewriting-technical-prose-naturally/scripts/check_prose.mjs --warn <기록.md> (44건)",
"exit": 0
},
{
"cmd": "node .agents/skills/writing-tech-log-records/scripts/check_evidence.mjs virtualization --repo",
"exit": 0
},
{
"cmd": "python3 scripts/build-tech-log-tree.py virtualization",
"exit": 0
},
{
"cmd": "python3 scripts/verify-tech-log-tree.py virtualization",
"exit": 0
},
{
"cmd": "python3 scripts/audit-records.py virtualization",
"exit": 0
}
],
"notes": "기록 44건을 서브에이전트 12개에 나눠 동시에 썼다(메모리 20건 = S3-A·B 개념 6 / S3-C 참조 2+질문 2 / S3-D·E 질문 8, 네트워크 10건 = S3-F 개념 1+참조 2 / S3-G·H 질문 7, 스토리지 14건 = S3-I·J 개념 4 / S3-K 참조 3+질문 2 / S3-L 질문 5). 같은 단계의 서로 다른 기록이라 병렬로 돌렸고, 프로젝트 전체를 훑는 검사기(check_evidence·build·verify-tree·audit)는 배치가 서로의 반쯤 쓴 파일을 보지 않도록 오케스트레이터가 열둘이 끝난 뒤 한 번만 돌렸다. 열두 배치가 같은 것을 지켰다 — Reference·Question 은 평문 칸이라 백틱·코드펜스·표·그림을 넣지 않았고, 명령은 SSOT 에 적힌 것만 쓰고 SSOT 가 명령을 안 적은 확인은 명령을 짓지 않고 그 사실을 적었으며, 이 Host 에서 잰 값은 하나도 만들지 않고 SSOT 의 예시 숫자는 예시라고 밝혔다. 오케스트레이터가 런 도중에 고친 것 둘. (1) 계약 제목 「vCPU 배치와 메모리 배치가 NUMA 에서 한 묶음이 되는 자리」가 check_prose 의 spatial-metaphor 를 error 로 밟아 계약과 기록을 함께 「NUMA 에서는 vCPU 배치와 메모리 배치를 함께 본다」로 고쳤다. 배치 셋이 각자 다른 우회 표현을 쓰고 있어 그것도 새 제목으로 맞췄다. (2) topicName 이 배치마다 갈렸다 — 기존 CPU 기록 13건은 짧은 「CPU 가상화」인데 새 기록들이 계약 주제의 긴 title 을 넣었다. Studio 주제 이름이 될 칸이라 44건을 「메모리 가상화」·「네트워크 가상화」·「스토리지 가상화」로 맞췄다. 계약 storage 주제의 title·readerQuestion·노드 제목에 있던 백틱 6곳도 지웠다 — 평문으로 렌더링되는 칸이다. check_body 가 문단 안의 꺾쇠 자리표시자(<device> 같은 것)를 inline html 로 거절해 네 배치가 자리표시자를 말로 풀어 썼다. 그림은 아무도 만들지 않았다 — 아홉 기록이 「그림 필요」를 근거 절 앵커와 함께 적어 S4 로 넘겼고, 개념 둘(huge-pages-in-a-vm · qemu-block-backend-forms)은 표가 답한다고 판단해 청구하지 않았다."
},
{
"id": "S4",
"name": "기록 → 그림",
"skill": "technical-visualizer",
"runBy": "subagent",
"status": "DONE",
"skipReason": "",
"skillEcho": "Every factual boundary/group, node, and edge must cite document line ranges. Unsupported content must be `assumption: true` with no evidence.",
"inputs": [
"docs/virtualization/tech-log-studio/*/concept/*.md",
"docs/virtualization/final/document.md"
],
"outputs": [
"docs/virtualization/final/assets/diagrams/guest-memory-address-translation-path/guest-memory-address-translation-path.svg",
"docs/virtualization/final/assets/diagrams/page-fault-layers-in-a-vm/page-fault-layers-in-a-vm.svg",
"docs/virtualization/final/assets/diagrams/virtio-balloon-inflate-deflate/virtio-balloon-inflate-deflate.svg",
"docs/virtualization/final/assets/diagrams/numa-vcpu-and-memory-placement/numa-vcpu-and-memory-placement.svg",
"docs/virtualization/final/assets/diagrams/packet-control-and-data-paths/packet-control-and-data-paths.svg",
"docs/virtualization/final/assets/diagrams/guest-block-io-to-virtqueue/guest-block-io-to-virtqueue.svg",
"docs/virtualization/final/assets/diagrams/write-completion-boundaries/write-completion-boundaries.svg",
"docs/virtualization/final/assets/diagrams/vms-sharing-one-nvme/vms-sharing-one-nvme.svg",
"docs/virtualization/final/assets/diagrams/vm-exit-handling-cycle/vm-exit-handling-cycle.svg",
"docs/virtualization/tech-log-studio/tech-log-tree.json"
],
"gates": [
{
"cmd": "./scripts/techviz lint docs/virtualization/final/.techviz/<이름>/spec.json --context .../context.json (9장)",
"exit": 0
},
{
"cmd": "python3 scripts/check-figure-text.py virtualization",
"exit": 0
},
{
"cmd": "python3 scripts/check-figure-overlap.py virtualization",
"exit": 0
},
{
"cmd": "python3 scripts/preview-figure.py (PNG 로 떠서 눈으로 봤다)",
"exit": 0
},
{
"cmd": "python3 scripts/verify-project-layout.py virtualization",
"exit": 0
},
{
"cmd": "python3 scripts/build-tech-log-tree.py virtualization",
"exit": 0
},
{
"cmd": "python3 scripts/verify-tech-log-tree.py virtualization",
"exit": 0
}
],
"notes": "서브에이전트 넷(S4-A·B·C 신규 · S4-D 기존 그림 재대조). 3단계가 청구한 아홉 중 여덟을 그렸다. 못 그린 하나 — memory-pressure-to-storage-contention(네 갈래 I/O 가 한 NVMe 로 모이는 그림). 근거 절 §62 로 prepare 한 문맥이 허용하는 profile 이 sequence 하나뿐인데 그 절이 「Guest와 Host가 동시에 memory pressure를 겪으면」이라고 못 박아 순서가 없다. 순서를 지어내야 그려져서 멈췄고 반쯤 만든 .techviz 폴더도 지웠다 — SKILL.md 가 「Stop and report metadata.source_gap instead of fabricating」라고 적은 자리다. 개념 열하나 중 huge-pages-in-a-vm 과 qemu-block-backend-forms 는 3단계가 「본문 비교표가 답한다」로 청구하지 않았다. profile 은 문맥이 정했다 — component-flow 넷(주소 변환 경로 · page fault 계층 · 블록 I O 경로 · 완료 경계 · NVMe 수렴 중 다섯), sequence 둘(balloon · NUMA). 기각과 재작업이 여러 번 있었고 사유는 spec 의 metadata.rationale 에 남겼다. 검사기가 못 잡고 사람 눈이 잡은 것 셋 — (1) group 이름이 경계를 넘는 엣지 라벨에 덮여 「Guest Kerne」로 잘림, (2) 레이아웃이 노드를 group 별로 모으지 않아 Host 상자가 Guest 노드까지 감쌈, (3) device model 에서 나가는 점선이 옆 라벨을 관통. 셋 다 lint 와 겹침 검사기는 PASS 였다. S4-D 는 SSOT 가 절 28개에서 177개로 커지며 §1~§28 의 줄 번호가 +14 밀린 것을 vm-exit-handling-cycle 의 정본에 반영했다 — 세 절의 text 가 문자열로 동일한 것을 먼저 확인하고 evidence 줄 번호 38개와 sha256 만 옮겼다. SVG 의 좌표는 한 값도 바뀌지 않았다. 오케스트레이터가 계약을 되적었다 — 개념 노드 여덟에 ssot-assets, assetLedger 에 배정 아홉과 그림을 안 받은 개념 셋의 사유."
},
{
"id": "S5",
"name": "AI 티 제거",
"skill": "rewriting-technical-prose-naturally",
"runBy": "subagent",
"status": "DONE",
"skipReason": "",
"skillEcho": "### Write Korean words in Korean. Latin script is for identifiers only",
"inputs": [
"docs/virtualization/tech-log-studio/*/*/*.md (44건)"
],
"outputs": [
"docs/virtualization/tech-log-studio/tech-log-tree.json"
],
"gates": [
{
"cmd": "node .agents/skills/rewriting-technical-prose-naturally/scripts/check_prose.mjs --warn <기록.md> (44건)",
"exit": 0
},
{
"cmd": "node .agents/skills/rewriting-technical-prose-naturally/scripts/style_profile.mjs <기록.md> (44건)",
"exit": 0
},
{
"cmd": "python3 scripts/studio-body.py <기록.md> -o /tmp/sb5-<slug>.md (44건)",
"exit": 0
},
{
"cmd": "node --experimental-transform-types .agents/skills/writing-tech-log-records/scripts/check_body.mjs /tmp/sb5-<slug>.md (44건)",
"exit": 0
},
{
"cmd": "node .agents/skills/writing-tech-log-records/scripts/check_evidence.mjs virtualization --repo",
"exit": 0
},
{
"cmd": "python3 scripts/audit-records.py virtualization",
"exit": 0
}
],
"notes": "서브에이전트 아홉(S5-A~I)이 44건을 나눠 제자리에서 고쳤다. 고친 것은 대부분 같은 종류다 — 자리잡은 외래어를 한글로 옮기고(호스트·게스트·메모리·페이지·패킷·큐·스토리지·지연), 영어 용어는 첫 자리에서 한 번만 「한글 뜻(English)」로 풀고, 120자 넘는 문장을 주어가 바뀌는 자리에서 끊고, 자료에 이미 있는 인과를 문장 안으로 이었다(연결어미). 대표 수치: 문장당 맨몸 영문 5~12 → 2.4~8, 한글 비율 0.43~0.55 → 0.58~0.72. 보호 구간은 지켰다 — 코드블록·명령어·수치·직접 인용·frontmatter·계약 title·관계 절의 다른 기록 제목이 원문 그대로인 것을 각 에이전트가 대조했고, 오케스트레이터가 끝에 check_evidence 로 다시 봤다(문제 없음). 남긴 것 셋. (1) style_profile 의 「문장당 맨몸 영문」이 Question·Reference 여러 건에서 기준 위로 남는다. 그 종류는 칸이 평문이라 백틱을 못 쓰고, 검사기가 frontmatter 의 source 앵커와 영문 title 까지 산문에 섞어 세며, 남은 라틴은 SSOT 를 그대로 옮긴 명령·열거·다른 기록 제목이다. 수치를 맞추려면 보호 구간을 건드려야 해서 멈췄다 — 스킬이 「수치를 맞추려고 문장을 넣지 마라」고 적은 자리다. (2) density.mjs 는 본문 없는 종류에 걸지 않았다. 본문 있는 개념 셋(memory-pressure·virtio-balloon·numa)이 「절당 낱말」과 「1,000낱말당 수치」에 걸리는데, 이 SSOT 에 이 Host 에서 잰 값이 하나도 없어 채우려면 없는 사실을 만들어야 한다. (3) 에이전트들이 문체 밖의 문제를 넘겼다 — 본문이 인용한 절 번호가 frontmatter 의 source 에 없는 경우 몇 건, reference-a-speedup 의 양상(SSOT 는 당위인데 기록은 서술), reference-record-the-conditions 규칙 5 가 SSOT 의 6~9 단계를 건너뛴 것. S5 범위가 아니라 고치지 않고 적어 둔다."
},
{
"id": "S6",
"name": "일한 사람의 목소리",
"skill": "writing-as-the-person-who-did-it",
"runBy": "subagent",
"status": "DONE",
"skipReason": "",
"skillEcho": "고치는 방법은 하나뿐이다. **자료에 남아 있는 사람의 흔적을 찾아서 제자리에 놓는다.**",
"inputs": [
"docs/virtualization/tech-log-studio/*/*/*.md (44건)",
"docs/virtualization/final/document.md",
"docs/virtualization/tech-log-studio/tech-log-tree.json"
],
"outputs": [
"docs/virtualization/tech-log-studio/tech-log-tree.json"
],
"gates": [
{
"cmd": "node .agents/skills/writing-as-the-person-who-did-it/scripts/check_voice.mjs <기록.md> (57건 전수)",
"exit": 0
},
{
"cmd": "node .agents/skills/rewriting-technical-prose-naturally/scripts/check_prose.mjs --warn <기록.md> (57건 전수)",
"exit": 0
},
{
"cmd": "python3 scripts/studio-body.py <기록.md> -o /tmp/sb6-<slug>.md (44건)",
"exit": 0
},
{
"cmd": "node --experimental-transform-types .agents/skills/writing-tech-log-records/scripts/check_body.mjs /tmp/sb6-<slug>.md (44건)",
"exit": 0
},
{
"cmd": "node .agents/skills/writing-tech-log-records/scripts/check_evidence.mjs virtualization --repo",
"exit": 0
},
{
"cmd": "python3 scripts/audit-records.py virtualization",
"exit": 0
}
],
"notes": "흔적 있음. 서브에이전트 아홉(S6-A~I)이 44건을 나눠 봤고, 넣은 문장은 배치별로 5~15개다. 이 프로젝트에는 코드 저장소도 커밋도 주석도 없고 이 Host 에서 잰 값도 없어, 쓸 수 있는 흔적은 두 종류뿐이었다 — (1) SSOT 자신이 못 박아 둔 문장(「잘못된 이해」를 먼저 그린 §44, 「정확한 표현:」으로 뽑은 §156, 「단정하면 안 되는 이유」를 절 제목으로 삼은 §157, 「Host-side release 동작은 버전과 설정에 따라 달라질 수 있다」는 §67), (2) 사람이 분해 계약에 손으로 적은 처분 사유 — 왜 이것만 독립 기록이 되고 나머지는 흡수됐는지, 왜 이 물음을 다른 물음과 합치지 않았는지, 무엇을 재지 않았는지. 그 둘을 요약하지 않고 그 주장 옆으로 옮겼다. 안 넣은 것도 배치마다 적었다 — 「처음에는」·「고민 끝에」·「놀랍게도」는 한 건도 쓰지 않았고, 예상과 어긋난 자리는 이 Host 에서 잰 값이 없어 쓸 근거가 없었고, 누가 실제로 오독했다는 기록이 없어 「~로 읽기 쉽다」류를 만들지 않았다. 한 배치(S6-E)는 담당 넷 중 하나(question:network-virtualization-cpu-cost-under-load)를 한 글자도 고치지 않았다 — 상류의 판단이 이미 본문에 다 들어가 있었다. 검사 중에 새로 난 error 는 그 자리에서 고쳤다(spatial-metaphor 「그 자리에」·「같은 자리에 있다」, naming-instead-of-telling 「밝혀 둔 것이다」). 오케스트레이터가 기록 57건 전수에 check_voice 와 check_prose 를 다시 돌려 실패 0 을 확인했다. 넘어온 것 하나 — question:host-block-device-under-the-disk-image 의 본문이 §163 을 대는데 그 기록의 source 앵커에 §163 이 없다. check_evidence 는 산문의 절 번호를 대조하지 않아 통과하지만 계약과는 어긋난 자리다."
},
{
"id": "S7",
"name": "Studio 저장",
"skill": "publishing-tech-log-to-studio",
"runBy": "subagent",
"status": "DONE",
"skipReason": "",
"skillEcho": "기록 `.md` 하나를 Studio 편집 화면에 넣고 **저장**한다. 거기서 끝난다.",
"inputs": [
"docs/virtualization/tech-log-studio/*/*/*.md (44건)",
"docs/virtualization/final/assets/diagrams/*/*.svg (8장)"
],
"outputs": [
"docs/virtualization/tech-log-studio/tech-log-tree.json"
],
"gates": [
{
"cmd": "상태 레일 `저장됨` 확인 (44건)",
"exit": 0
},
{
"cmd": "python3 scripts/build-tech-log-tree.py virtualization",
"exit": 0
},
{
"cmd": "python3 scripts/verify-tech-log-tree.py virtualization",
"exit": 0
},
{
"cmd": "python3 scripts/audit-records.py virtualization",
"exit": 0
},
{
"cmd": "python3 scripts/verify-project-layout.py virtualization",
"exit": 0
}
],
"notes": "처음에 인증이 안 돼 SKIPPED 로 적었다가 사용자가 로그인한 뒤 실제로 돌렸다. Playwright 는 브라우저 하나를 공유하므로 병렬로 못 돌린다 — 서브에이전트 여덟(S7-A~I)을 순차로 돌렸다. 오케스트레이터가 먼저 /studio/taxonomy 에서 주제 셋(메모리 가상화 · 네트워크 가상화 · 스토리지 가상화)을 만들었다. 기록 44건 전부 새 작업본을 만들고 칸을 채워 저장했고, 44건 모두 상태 레일이 `저장됨` 이며 frontmatter 에 id 와 studio 를 되적었다. 게시는 한 건도 하지 않았다. 그림 Asset 여덟을 본문보다 먼저 올려 서버 키를 받고 studio-body.py --key 로 본문을 바꿔 넣었으며, 미리보기에서 여덟 장 모두 img naturalWidth 가 0 이 아닌 것을 눈으로 확인했다. 화면이 계약과 다른 자리를 배치들이 찾아 적었다 — Question 은 사실→확인한 사실 · 미지수→남은 미지수 · 선택지→검토한 선택지이고 「닫는 조건」 칸이 없어 「다음 검증」 마지막 줄로 넣었다. Reference 는 목적→이 기준을 쓰는 이유 · 규칙→판단 기준 · 적용 조건→적용할 때 · 예외→예외와 주의. Concept 라디오 이름은 「개념」 이고 본문 칸은 「본문 Markdown」 이다. 이번 런에서 새로 드러난 Studio 쪽 한계 셋. (1) 값이 조용히 잘린다 — 제목 30/31자 · 기준 버전 66/107자 · 본문 4157/4187자로 잘려 저장된 일이 있었다. 이후 모든 배치가 넣은 뒤 되읽어 글자 수까지 대조하고 어긋나면 다시 채웠다. (2) Asset 의 대체 텍스트가 300자를 넘으면 업로드가 500 으로 실패한다(319·341·348자에서 재현). 저장소 .md 의 alt 는 그대로 두고 Asset 메타데이터의 alt 만 줄였다. (3) 관계 대상 드롭다운이 100건 상한이고 서버가 limit>100 을 422 로 막는다. 이번에 문서 총수가 100 을 넘으면서 목록에서 밀려나는 대상이 생겨, 마지막 두 배치가 catalog 요청을 가로채 q= 검색 결과를 합쳐 넣고 화면의 정상 경로로 골랐다. 또 「판단 기준」 행의 제목 input 에 type=\"text\" 속성이 없어 흔한 셀렉터로 안 잡히고 다섯 칸이 조용히 빈 적이 있다 — 되읽기 대조가 잡았다. 관계는 상대가 아직 Studio 에 없으면 못 걸리므로 배치마다 비워 두었다가 뒤 배치가 되돌아가 채웠다(네트워크 12건 · 스토리지 14건 · 마지막 10건). 마지막 배치가 기존 관계가 사라지지 않은 것(lostRelations 0)과 기록 57건 전부 id·studio 를 갖고 있는 것을 대조했다."
}
]
}