Files
document-haness/docs/keycloak-session-store/final/.techviz/ghost-row-cleanup-order/spec.json
T
DongHyeonkaandClaude Opus 5 2109f726fe feat(pipeline): keycloak-session-store 25편·virtualization 59편을 S3→S5→S6 으로 돌린다
기록 84편을 계약 에이전트로 다시 썼다. 기존 71편(kss 25 · virt 46)과, 계약에만
있고 안 쓰여 있던 새 글감 13편이다. 원장 84개를 열어 단계마다 스킬 영수증과 관문
종료 코드를 적었고 verify-pipeline-run.py 가 error 0 으로 닫는다.

SSOT 결함 둘을 고쳤다.

- kss 의 `약 58일` 이 반입 중 `약 59일` 로 바뀌어 있었다. 원 증거 파일이
  「남은 일수: 88일 … 실제 갱신까지 약 58일」로 산수를 직접 적는다. D-4a 쪽
  `약 59일` 은 강제 갱신 뒤(`VALID: 89 days`)라 맞는 값이라 그대로 뒀다.
- virt §198 의 `11.6GB` 는 §178 의 원 측정 `Mem: 11648`(MiB)과 어긋나는데
  원 가이드의 표기 그대로라 고치지 않고 쓰이는 자리에 대조를 적었다.

기록의 수치 오류 셋을 고쳤다 — CASE 요약의 「게스트 셋에 8240MB」(5120+3120 은
둘이다), k3s 편이 같은 것을 여섯·일곱·여덟로 세던 것, no-docker 편의 「셋을 더
든다」(§281 의 표는 네 행이고 디스크 행이 빠져 있었다).

계약을 셋 고쳤다.

- kss 의 sourceRepository 리비전이 cdac9b8 이었는데 그 커밋에는 docs/guides/**
  28개가 아예 없다. 9465582b 로 바꾸고, 반입한 바이트가 어느 커밋과도 같지 않다는
  것을 측정값과 함께 적었다 — 반입은 커밋이 아니라 그 시점의 작업 트리에서 떠 온
  것이다(kss 297/306 · virt 12/14 가 작업 트리와 같고, 200 커밋을 거슬러 전수
  대조했을 때 가장 가까운 커밋도 28개가 어긋났다).
- virt 계약이 「2026-09-11 재배분」이라고 적는데 SSOT 는 재배분 날짜를 적지 않고
  재배분 뒤 값은 이미 2026-09-10 측정에 찍혀 있다.
- kss 후보 대장이 지나친 절 아홉에 처분을 적었다(warn 9 → 0). 새 글감은 0건이고
  넷은 앵커가 h3 슬러그의 접두가 아니라 중간 토막이라 검사기가 못 본 것이었다.

style_profile.mjs 의 결함 둘을 고쳤다 — frontmatter 가 문장으로 세어져
(실측 398자짜리 「문장」 하나) 평균 길이를 기준 안으로 밀어 올리고 있었고,
engPerSent 의 분자는 목록을 포함한 글에서, 분모는 목록을 걷어낸 글에서 세고
있었다(Question 기록에서 11.94 → 3.86).

verify-pipeline.py 전 항목 PASS · error 0 · unittest 334건 OK.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-17 11:01:55 +09:00

190 lines
5.6 KiB
JSON

{
"version": "1.1",
"id": "ghost-row-cleanup-order",
"title": "유령 행을 지운 쪽과 그 시각",
"question": "SIGKILL 로 끊긴 노드의 JGROUPS_PING 행은 누가, 언제 지우는가",
"type": "sequence",
"direction": "LR",
"audience": [
"Keycloak 클러스터를 쿠버네티스에 올리는 엔지니어"
],
"summary": "행을 지운 화살표는 죽은 노드가 아니라 남아 있는 코디네이터에서 나오고, 클러스터 뷰가 바뀐 초와 같은 초에 찍힌다.",
"alt": "kubectl 이 강제 종료한 Keycloak 노드가 클러스터에서 빠지고, 남은 노드가 JGROUPS_PING 의 행을 지운 뒤 다른 이름의 새 노드가 합류하는 시간 순서.",
"long_description": "왼쪽부터 kubectl, keycloak-0-60375, keycloak-1-36736, JGROUPS_PING, keycloak-0-16105 다섯 참여자가 생명선으로 선다. 1번 메시지에서 kubectl 이 keycloak-0-60375 를 --grace-period=0 --force 로 끊는다. 2번에서 07:40:28 에 남은 노드 keycloak-1-36736 의 뷰에서 그 노드가 빠진다. 3번이 이 그림의 중심이다 — 같은 07:40:28 에 JGROUPS_PING 의 행을 지우는 화살표가 keycloak-1-36736 에서 나온다. 강제 종료로 이미 끊긴 keycloak-0-60375 의 생명선에서는 테이블로 가는 화살표가 없다. 4번에서 20초 뒤 07:40:48 에 keycloak-0-16105 가 합류한다. 돌아온 노드의 이름은 접두사 keycloak-0 만 같고 접미사가 다르다.",
"source_context": {
"document": "docs/keycloak-session-store/final/document.md",
"document_sha256": "88a081390dff22cd4171d5f9b534e46a37f6295c3b2652bc4c6fff0b578d5c6b",
"anchor": {
"kind": "heading",
"value": "관측 (observed)",
"line": 892
}
},
"composition": {
"profile": "sequence",
"diagram_only": true,
"reference_ids": [
"payment-approval-sequence"
],
"rationale": "지배적 질문이 「누가 언제 지웠나」라 참여자 사이의 시간 순서가 논지다. 정적 구성도로 그리면 행을 지운 주체가 어느 생명선에서 나오는지가 사라진다.",
"focus_node": "coordinator"
},
"groups": [],
"nodes": [
{
"id": "kubectl",
"label": "kubectl",
"kind": "participant",
"role": "participant",
"description": "파드를 정상 종료와 강제 종료로 끊는 쪽.",
"evidence": [
{
"start_line": 886,
"end_line": 888
}
],
"assumption": false
},
{
"id": "dying",
"label": "keycloak-0-60375",
"kind": "participant",
"role": "participant",
"details": [
"SIGKILL"
],
"emphasis": "warning",
"description": "강제 종료로 끊긴 노드. 자기 행을 지우고 나갈 틈이 없다.",
"evidence": [
{
"start_line": 898,
"end_line": 901
}
],
"assumption": false
},
{
"id": "coordinator",
"label": "keycloak-1-36736",
"kind": "participant",
"role": "participant",
"details": [
"코디네이터"
],
"emphasis": "primary",
"description": "남아 있는 코디네이터. 정리 주체다.",
"evidence": [
{
"start_line": 914,
"end_line": 916
}
],
"assumption": false
},
{
"id": "pingtable",
"label": "JGROUPS_PING",
"kind": "participant",
"role": "participant",
"description": "노드 행이 등록되는 발견 테이블.",
"evidence": [
{
"start_line": 888,
"end_line": 888
}
],
"assumption": false
},
{
"id": "rejoined",
"label": "keycloak-0-16105",
"kind": "participant",
"role": "participant",
"details": [
"새 접미사"
],
"description": "복구 뒤 올라온 노드. 접두사만 같다.",
"evidence": [
{
"start_line": 918,
"end_line": 920
}
],
"assumption": false
}
],
"edges": [
{
"id": "m1",
"from": "kubectl",
"to": "dying",
"label": "delete pod --force",
"kind": "request",
"order": 1,
"evidence": [
{
"start_line": 886,
"end_line": 888
}
],
"assumption": false
},
{
"id": "m2",
"from": "dying",
"to": "coordinator",
"label": "이탈 07:40:28",
"kind": "event",
"style": "dashed",
"order": 2,
"evidence": [
{
"start_line": 906,
"end_line": 907
}
],
"assumption": false
},
{
"id": "m3",
"from": "coordinator",
"to": "pingtable",
"label": "행 삭제 07:40:28",
"kind": "data",
"emphasis": "primary",
"order": 3,
"evidence": [
{
"start_line": 897,
"end_line": 898
},
{
"start_line": 914,
"end_line": 916
}
],
"assumption": false
},
{
"id": "m4",
"from": "rejoined",
"to": "coordinator",
"label": "합류 07:40:48",
"kind": "event",
"style": "dashed",
"order": 4,
"evidence": [
{
"start_line": 908,
"end_line": 909
}
],
"assumption": false
}
],
"legend": [],
"metadata": {
"rationale": "코디네이터 로그는 뷰 변경만 보여 주고 JGROUPS_PING 의 행이 어느 생명선에서 지워지는지는 보여 주지 않는다. 그 화살표 하나를 자리로 세우려고 sequence 를 골랐다."
}
}