ADR 상세 페이지 Phase D — PR 표 분리 + 교훈/이월 callout

요약Sprint 161에서 분할 이월된 Phase D 범위 실행 — ADR detail의 PR 표를 본문 prose에서 분리하여 PhaseStrip 카드와 중복 차단

날짜
영향도높음

주요 결정

sections 단위 chunk 렌더 + callout in-place 삽입

본문 markdown을 sections 순회하며 prose 누적 → lessons/carryover H2 만나면 flush + callout wrapper를 그 위치에 삽입. ordering 회귀 0

callout = wrapper, content 100% 보존

list-entry 변환(sprint chip 등) 부가 가치는 폐기, lessons/carryover 그룹 raw markdown(H2 헤딩만 제거 + H3 포함)을 wrapper 안에 prose 렌더. H2/H3 mixed prose 누락 0

terminal 검사 폐기

chunk 렌더가 in-place 삽입을 책임지므로 terminal 검사 불필요. 모든 ADR에서 callout 표시

tolerant heading matching

CARRYOVER_RE + LESSONS_RE로 KR/EN/numbered prefix(9.)/plus suffix(137+)/variant 헤딩(주요 교훈, Carry-Over Seeds) 모두 커버

PR 표 strip은 implementation H2 안에서만

PhaseStrip이 phases를 시각화하는 경우에만 표 라인 정밀 제거. graceful degradation

목표

  • Sprint 161에서 분할 이월된 Phase D 범위 실행 — ADR detail의 PR 표를 본문 prose에서 분리하여 PhaseStrip 카드와 중복 차단
  • 교훈/이월 섹션을 callout 박스(💡 / 📋)로 시각 강조 — H2 단순 헤딩에 그쳤던 핵심 정보의 가시성 향상
  • Sprint 162 Critic R1 P3 이월 해소: 기존 ADR에 Mermaid 다이어그램 확대 적용 (sprint-157 P1~P10 + hotfix 사이클 시각화)

결정

  • sections 단위 chunk 렌더 + callout in-place 삽입: 본문 markdown을 sections 순회하며 prose 누적 → lessons/carryover H2 만나면 flush + callout wrapper를 그 위치에 삽입. ordering 회귀 0
  • callout = wrapper, content 100% 보존: list-entry 변환(sprint chip 등) 부가 가치는 폐기, lessons/carryover 그룹 raw markdown(H2 헤딩만 제거 + H3 포함)을 wrapper 안에 prose 렌더. H2/H3 mixed prose 누락 0
  • terminal 검사 폐기: chunk 렌더가 in-place 삽입을 책임지므로 terminal 검사 불필요. 모든 ADR에서 callout 표시
  • tolerant heading matching: CARRYOVER_RE + LESSONS_RE로 KR/EN/numbered prefix(9.)/plus suffix(137+)/variant 헤딩(주요 교훈, Carry-Over Seeds) 모두 커버
  • PR 표 strip은 implementation H2 안에서만: PhaseStrip이 phases를 시각화하는 경우에만 표 라인 정밀 제거. graceful degradation

구현 (단일 PR, 브랜치 feat/sprint-163-adr-pr-table-callouts, 12 commits)

Phase담당변경라인
A — PR 표 strip 기반(parser/types)architectparser.ts + types.ts+269 +27
B — Lessons/Carryover 추출 + i18narchitectparser.ts + i18n.ts + section-aliases.ts+10 +20
C — callout 컴포넌트 + detail-view 통합architectadr-lessons-callout.tsx 신규 + adr-carryover-callout.tsx 신규 + adr-detail-view.tsx+57 +73 +(±)
D — sprint-157 Mermaid 다이어그램architectsprint-157.md KR+EN+22 ×2
R1 P2 — EN carryover headingarchitectsection-aliases.ts+20 −4
R2 P2 — terminal 검사 + TOC anchorarchitectparser.ts + callout 컴포넌트 2개 + adr-detail-view.tsx+99 −5
R3 P2 — TOC H2 유지 (H3만 strip)architectadr-detail-view.tsx+12 −9
R4 P2/P3 — chunks 렌더 + numbered prefixarchitectparser.ts + section-aliases.ts + adr-detail-view.tsx+150 −53
R5 P2 — preamble seedarchitectadr-detail-view.tsx+19
R6 P2 — prose-only H3 유지architectparser.ts + adr-detail-view.tsx+46 −12
R7 P2 — callout을 wrapper로 전환architectcallout 2개 + adr-detail-view.tsx+78 −118
R8 P2 — plus-suffixed sprint headingarchitectsection-aliases.ts+1 −1
R9 P2 — lessons tolerant matchingarchitectsection-aliases.ts+11

세부 변경

  1. parser.ts: extractLessons/extractCarryover/buildBodyMarkdownForProse/stripPrTableLines/getCanonicalSectionIndices/isCanonicalTerminal/hasTopLevelListItem 추가. H3 sub-section 통합(collectCanonicalSectionMarkdown), dash + 숫자 list + em-dash 구분자 인식
  2. types.ts: AdrLessonEntry / AdrCarryoverEntry / AdrDoc.bodyMarkdownForProse|lessons|carryover 필드 추가
  3. section-aliases.ts: CARRYOVER_RE(numbered/plus/EN/parenthetical 모두) + LESSONS_RE 추가, numbered prefix 정규화
  4. i18n.ts: lessonsTitle/carryoverTitle/carryoverSprintPrefix KR+EN
  5. adr-lessons-callout.tsx 신규: 💡 + callout-warn 톤 wrapper, prose-headings/p/li/strong fg 색상 매핑
  6. adr-carryover-callout.tsx 신규: 📋 + callout-info 톤 wrapper
  7. adr-detail-view.tsx: renderSectionChunks 도입 — preamble seed + sections H2 단위 chunk + lessons/carryover wrapper in-place + implementation PR 표 strip + TOC filter
  8. docs/adr/sprints/sprint-157.md + EN: P1~P10 + hotfix 사이클 flowchart Mermaid 추가 (phase/hotfix/realfix 3색 분기)

검증

항목결과
tsc --noEmitclean (0 errors)
npm run build247 페이지 정적 export 성공
check-adr-links blog/out/adr1246 links 0 broken
check-adr-en-coverage --strict111/111 (100.0%) PASS
Critic R1 (Codex gpt-5)P2 1건 EN carryover heading 미커버 → 해소
Critic R2P2 2건 TOC out-of-sync + section ordering → 해소
Critic R3P2 1건 TOC H2 누락 → 해소
Critic R4P2 callout 순서 회귀 + P3 numbered heading → chunks 렌더 + numbered prefix 정규화
Critic R5P2 1건 preamble 누락 → seed 추가
Critic R6P2 1건 prose-only H3 누락 → list-bearing H3만 흡수
Critic R7P2 2건 H2/H3 mixed prose 누락 → callout wrapper 전환 (list-entry 변환 폐기, content 100% 보존)
Critic R8P2 1건 plus-suffixed sprint → 정규식 fix
Critic R9P2 1건 lessons tolerant heading → LESSONS_RE 추가
Critic R10PASS — "no discrete regression"

브랜치 규율 ✅ 31 스프린트 연속 준수

  • 신규 브랜치 feat/sprint-163-adr-pr-table-callouts + Squash merge 예정
  • main 직접 commit 0건, --no-verify 0건

신규 패턴

  1. sections 단위 chunk 렌더 + callout in-place 삽입 — 본문 markdown을 H2 단위 chunk로 분할하여 callout을 원래 위치에 정확히 삽입. ordering 회귀 차단 + 시각 강조 동시 달성
  2. callout = wrapper, content 100% 보존 — list-entry 변환은 부가 가치, 본문 보존이 핵심. wrapper가 raw markdown 그룹을 prose 안에 렌더하면 H2/H3 prose/list/separator 모든 content 자연 표시
  3. tolerant heading matching (CARRYOVER_RE + LESSONS_RE) — 정확 alias 매치 + 정규식 fallback 이중 layer. numbered prefix, plus suffix, parenthetical suffix, KR/EN variant 모두 커버
  4. preamble seed 패턴 — frontmatter-less ADR의 첫 H2 직전 dash-list 메타가 sections 외부에 있는 한계를 본문 prefix slice로 seed. detail-view 상단 H1과 중복 차단 정규식 포함
  5. Critic 10 라운드 회귀 적발 패턴 — R1~R9 모두 P2 발견. 단순 정규식 변형부터 본질적 ordering/content 보존까지 점진 노출. R7에서 list-entry 변환 자체를 폐기하는 본질 결정 도출
  6. callout 토큰 4종 활용 분기 — 기존 callout-warn(교훈, 노란 톤) / callout-info(이월, 파란 톤) 토큰 재사용으로 Palette 신규 매핑 0건. prose-headings:text-* 등 prose 색상 매핑은 callout fg 일관

관련 문서

  • sprint-162.md — 직전 sprint, Mermaid 활성화 + Critic P3 이월 인수
  • sprint-161.md — Phase D 분할 출발점, sections 단위 시각화 패턴
  • sprint-157.md — 본 sprint Phase D Mermaid 다이어그램 추가 대상