본문으로 이동

문서 스킬 연동

요약

문서 스킬 연동은 repo-docs-figures 스킬의 그림 도구 표에서 D2와 Vega-Lite 두 행을 이 도구 한 행으로 바꾸는 계약이다. 스킬의 그림 종류, 차트 종류, 색표, 글꼴, 변환 명령, 검사가 이 도구의 무엇에 대응하는지 정한다. 터미널 데모(VHS)는 그대로 둔다. 이 문서는 현재 계약과 확인한 증거만 적는다. 진행 기록, 검수 영수증, 이전에 남긴 검증 근거는 GitHub 이슈 요약에 둔다.

동기

지금 문서 스킬은 구조 그림을 D2로, 실험 차트를 Vega-Lite로 그리고, 두 도구에 같은 색을 넣으려고 변환 스크립트가 각 도구의 설정 형식으로 색표를 따로 넣는다. 글꼴은 보는 쪽에 설치되어 있어야 하고, D2 SVG에는 한글 글꼴이 들어가지 않는다. 도구가 하나면 색표, 글꼴, 여백, 움직임이 한 곳에서 정해지고, 스킬 규칙도 짧아진다.

예시

구성 요소 그림 변환

  1. 기여자가 docs/assets/architecture.thinkflow를 고친다.
  2. 기여자가 저장소 루트에서 python3 <스킬 폴더>/scripts/render_figures.py docs/assets/architecture.thinkflow를 실행한다.
  3. 스크립트가 thinkflow render --strict docs/assets/architecture.thinkflow를 부르고, 같은 폴더에 움직이는 SVG architecture.svg가 생긴다.
  4. 그림 검사 오류가 있으면 스크립트가 실패하고 결과 파일은 생기지 않는다.

실험 차트 변환

  1. 03-analyze가 results/summary.json을 쓴다.
  2. results/figures/accuracy.thinkflow의 data "../summary.json" at "/accuracy"가 그 값을 읽는다.
  3. 원본에 숫자를 손으로 적지 않는다.

상세 설계

그림 종류 대응

스킬 그림 지금 이 도구
맥락 그림 D2 direction: right, 그룹 system 기본 그래프, person, box system, external, store
구성 요소 그림 D2 그룹 system 안 구성 요소 기본 그래프, group system, 안에 box, store
순서 그림 D2 shape: sequence_diagram view sequence
상태 그림 D2 direction: down state, start, final, view graph down
데이터 그림 D2 shape: sql_table table, fk=
스킬 도형 규칙 이 도구
사용자: shape: person person
이 시스템: 이름이 system인 그룹 맥락 그림은 box system, 구성 요소 그림은 group system
구성 요소, 모듈: 기본 사각형 box
외부 프로그램, 외부 서비스: style.stroke-dash: 4 external
파일, 데이터베이스: shape: cylinder store
테이블: shape: sql_table table
  • 스킬의 “한 쌍에 선 하나, 방향은 요청이 가는 쪽” 규칙은 그림 문법이 오류로 지킨다. 스킬 문장에서 뺀다.
  • 스킬의 식별자 규칙(영어 소문자 kebab-case)은 그림 문법의 이름 규칙과 같다. 테이블 이름은 _를 쓰고, 열 이름은 대문자도 쓴다(그림 종류).
  • 스킬의 순서 그림 규칙(참여자는 처음 메시지를 보내는 순서)은 도구가 경고로 알린다(그림 종류).
  • Markdown 표는 이 도구의 대상이 아니다. 글로 된 표는 계속 Markdown 표로 쓴다.

차트 종류 대응

이 표는 스킬이 쓰는 Vega-Lite 차트가 도구의 무엇에 대응하는지만 정한다. 이 도구가 그리는 차트 종류 전체는 차트가 정한다.

스킬 Vega-Lite 차트 이 도구
bar와 errorbar, 기준선 rule chart bar, 계열.low, 계열.high, rule
덤벨 chart dumbbell
상자 그림 chart box
산점도 chart scatter
히트맵 chart heatmap
선 chart line
  • 스킬의 “값은 03-analyze가 넣고 손 기재 금지” 규칙은 data 줄로 지킨다.
  • 스킬의 “막대 축 0에서 시작, y축 둘 금지” 규칙은 차트가 지킨다. 스킬의 "계열 둘까지"는 스킬 쪽 제약이고 이 도구의 계열 수 계약이 아니다. 색 수를 넘는 계열은 아래 색 계약의 무늬·모양·직접 라벨로 구분한다.

디자인 기준과 수용 게이트

시각 기준은 Things 공식 사이트 culturedcode.com/things, 기능 페이지, 공식 네이티브 앱 화면 이미지다. 제목은 제목, 재생 조작은 조작, 카드는 카드처럼 역할이 같은 요소끼리 비교한다. 앱 화면 이미지도 역할 기준으로 유효하며 클래식 macOS 앱을 통째로 기준에서 빼지 않는다. 다만 지금 쓰는 앱 이미지는 2017년 사이트 영상 화면과 라이트·다크가 함께 있는 2018년 Things 3.7 화면이라 보조 참고이고, 현재 네이티브 버전과 같다는 근거가 아니다. UML 기호, 차트, 구성도처럼 직접 대응이 없는 요소는 같은 글자·면·선 규칙을 적용한 ThinkFlow 확장이지 Things의 구성 요소가 아니다. 예전에 쓰던 Refero 화면은 정규화한 측정값과 재구성 예제라 보조 참고일 뿐 기준이 아니다. Things의 로고와 제품 화면은 포함하지 않으며 별도 소개·문서 사이트도 만들지 않는다.

수용 게이트는 npm test와 별개의 화면 비교다. 모바일 320·390·430px와 데스크톱 실제 크기에서 공식 기준 화면과 나란히 비교하고, 라이트·다크와 정지·재생 중 상태를 확인한다. 필요한 브라우저가 없으면 게이트는 실패다. 건너뛴 검사를 통과로 세지 않는다. 자동 검사는 기능 증거이고 디자인 합격 증거가 아니며, 겹침·잘림 검사도 눈 검수를 대신하지 않는다. 정적 SVG 미리보기의 축소 이미지는 모바일 가독성 통과로 세지 않는다. 읽기용 HTML은 판의 자연 크기를 유지하고 남는 가로 넘침을 그림 영역에서 스크롤한다. 전체화면은 전체 맞춤과 확대를 제공한다.

계약

요소 계약
핵심 색 파랑·노랑·빨강·초록 넷. 값은 공식 사이트 solid 2024 기능 아이콘의 면색이고 순서와 함께 바꾸지 않는다(원색 값은 바뀌지 않는 기록이다). 2017년 사이트 영상 스틸과 2018년 앱 화면 이미지는 역할 위계를 보는 보조 참고이고 그 색을 현재 네이티브 색으로 읽지 않는다. 대비를 맞추려고 핵심 RGB를 바꾸지 않는다. 사이트 기능 아이콘 색은 네이티브 앱 모든 역할의 같은 색이라는 근거가 아니다. 면은 기준 원색을 그대로 쓰고 경계·글자·효과는 같은 계열에서 대비 역할에 맞춘 파생값을 사용한다. 관측한 페이지와 화면 위치는 이슈에 남긴다
확장 색 핵심 넷 밖의 색은 실제 팔레트 출처와 라이트·다크 실제 크기 구성 요소 검수를 거친 후보만 더한다. 지금 기록된 확장은 주황·보라·청록 셋이라 팔레트 개정 1의 계열은 일곱이다. 일곱은 개정 1의 기록일 뿐 고정된 최대가 아니다. 고른 순서는 한 번 기록하고 뒤에만 더하며 빌드마다 순열을 다시 찾지 않는다. 출처 없이 HEX를 고르지 않으며 이 문서에도 값을 복사하지 않는다
색 이동 고른 값 밖으로 색상·밝기를 자동으로 옮기지 않는다. 경계·글자색처럼 파생이 필요한 값은 후보 검수에서 고른 값으로 기록한다. 회색 윤곽을 섞지 않는다
같은 계열 경계와 효과 범주 색을 쓰는 차트 표식의 경계와 갱신 효과는 같은 계열을 따른다. 갱신 효과는 테두리를 같은 색상에서 밝힌 단계(color.data.category-effect.N, categoryPaint().effect)이며 원색을 바꾸지 않는다. 도형과 그룹의 켜짐·도착 후광은 tone과 무관하게 공통 효과(--fx-*)를 읽는다. 고른 색은 평소 면과 경계만 바꾼다. 효과 색은 일시적인 보조 신호라 대비 3으로 맞추지 않는다(같은 변화를 값 글자와 라벨도 알린다). 효과 후광이 라이트·다크에서 얼마나 잘 보이는지는 사람이 따로 평가하지 않았다(검증 요구사항, 미완료)
의미 아이콘 글리프 도형 안 의미 아이콘의 글리프 색(color.figure.icon-{역할}-ink)은 본문 글자색과 따로 둔 보조 역할이다. 다크에서는 같은 계열의 테두리 단계(dark-border)를 쓴다. 서비스와 사용자는 파랑, 데이터는 초록, 접근 제어는 노랑 계열이다. 원색(앵커)과 다크 카드 면은 바뀌지 않으므로 노랑처럼 카드 면 위 대비가 낮은 글리프도 색을 바꾸지 않고, 뜻은 도형 이름과 글자가 전한다. 이 낮은 대비를 접근성 기준 충족이라고 쓰지 않는다. 값은 토큰 소유 저장소가 정하며 이 문서에 복사하지 않는다. 라이트·다크 카드 위의 모습은 이번 개편 뒤 눈으로 검수하지 않았다(검증 요구사항, 미완료)
색 수 초과 색 수에 고정 상한이나 오류 상한을 두지 않는다. 색을 넘는 계열은 무늬·모양 단계와 직접 라벨로 구분하며 색만으로 구분하는 조용한 되감기를 두지 않는다
대비 계산 면 위 글자 색은 검은색과 흰색 중 계산한 대비가 큰 쪽이다. 글자는 4.5 이상이다. 그래픽은 그 요소가 실제 그려지는 면과 역할(선, 면, 효과)마다 그 면 위에서 잰다. 모든 그래픽에 일률로 3을 요구하지 않고, 3에 못 미치는 노랑을 맞추려고 색을 바꾸지 않는다. 라벨, 번호 키, 무늬, 모양이 구분을 보완한다
화살촉 일반 연결선은 채운 삼각형이다. UML 관계(상속·구현·집합·합성·의존)는 모양이 곧 뜻이라 의미 있는 예외로 둔다
부품 합성 카드(머리, 필드 줄), 선(연결선, 라벨), 화살촉, 아이콘, 탭, 도구 막대는 모양과 상태를 부품 하나가 소유하고 그림 종류마다 복제하지 않는다. 종류별 렌더러는 데이터와 필요한 배치 결과만 넘긴다. 같은 토큰을 읽는 것만으로 같은 부품이라 하지 않고, 측정과 그리기가 같은 부품의 역할 규약을 쓴다. 부품이 있는 파일과 부르는 쪽은 아키텍처의 호출 지도가 정한다
번호 배지 라이트는 어두운 면에 흰 숫자, 다크는 밝은 면에 어두운 숫자(color.figure.number-fill, number-ink). 범주 색을 쓰지 않는다. 글자 대비 4.5 이상
흐림 흐린 행은 면의 투명도만 낮추고 복제 테두리 같은 두 번째 경계층을 두지 않는다
사건 강조 지금 단계의 도형·선·이동 라벨은 한 공통 규칙으로 강조한다. 종류별 별도 강조를 두지 않는다
hover 도형과 카드에는 hover 효과가 없다. 장면 탭과 도구 막대 단추만 호버 때 켜지지 않은 항목의 면이 한 단계 짙어진다(color.control-hover). 키보드 초점(ui.focus 고리)과 눌림 상태는 접근성 때문에 유지한다
결함 수정 덮어쓰기 CSS와 예제별 보정을 쓰지 않고 공통 규칙을 고친다

증거 표

자동 증거는 저장소에 있는 검사의 이름이고, 화면 비교는 위 수용 게이트를 실제로 수행한 기록이다. 화면으로 확인한 범위는 표현 범위의 표가 정하고, 그 범위를 넘는 칸은 검증 요구사항, 미완료다. 이전에 남긴 검증 근거와 개수, 날짜는 GitHub 이슈 요약에 있다. 이전 모양의 화면 검수는 이번 개편(공통 장면 기본값, 한 낱말 색, 공통 도구 막대, Things 색 역할)의 근거가 아니다. 개편 뒤 화면으로 확인한 범위는 표현 범위의 표만 정하고, 이 표는 그 범위를 따로 주장하지 않는다. 자동 증거 칸이 "없음"인 항목은 직접 확인하는 자동 시험이 없다는 뜻이다.

항목 자동 증거 알려진 어긋남
글자 대비 없음. 화면 값은 npm run check가 토큰 수준에서 지킨다 면과 역할마다 잰 대비를 자동으로 다시 재지 않는다(검증 요구사항, 미완료)
핵심 색 역할의 공식 소스 대응 design-tokens 저장소의 검사(원색, 출처, 조정, 순서 기록, 역할 계산) 원색 값은 공식 이미지 안쪽 픽셀 표본이고 화면 비교는 아니다. 적록 색각 이상 시뮬레이션에서 빨강과 초록(0.066), 파랑과 보라(0.026)가 가깝다
그래픽·외곽선 대비 없음 라이트 노랑 경계는 실제 차트 면 위에서 3 미만이다. 색을 바꾸지 않고 직접 라벨, 번호 키, 같은 계열 점 테두리로 받으며, 이 그래픽 한계는 그대로 남아 있다. 흐린 행은 대비 3을 요구하지 않는다(차트)
한 낱말 색(tone)과 표현 방식(appearance) test/authoring.test.js가 모형과 거절을 확인한다 그려진 모습이 화면에서 구분되는지는 표현 범위의 표가 정한 범위만 확인했고 그 밖은 검증 요구사항, 미완료다
부품 합성(카드, 선, 화살촉, 아이콘, 탭, 도구 막대) test/components.test.js(U1~U9): 잰 카드와 그려진 카드의 일치, 머리 규칙, 글 이스케이프, 화살촉, 개념 아이콘의 단일 도형, 그림 틀의 도구 막대와 탭 줄. 사용자 아이콘의 안전은 test/escaping.test.js(I2) 카드 내용 줄, 순서 보기 참여자의 머리, 격자·큐 칸은 부품 시험이 아직 읽지 않는다. 부품의 모양이 화면에서 구분되는지, 기본 아이콘 세트의 표와 파일 일치도 자동으로 확인하지 않는다(검증 요구사항, 미완료)
hover 제거 없음 도형과 카드는 호버로 켜지지 않는다. 브라우저 동작이라 자동 시험이 없다
모바일 320·390·430px 넘침·글자 크기 없음 브라우저를 열지 않는 npm test는 이를 확인하지 않는다. 실제 Chrome 검수의 몫이고 확인한 폭과 장면은 표현 범위의 표가 정한다. 실제 기기와 Firefox는 확인하지 않았다
좁은 화면의 차트 가독성 없음 그래프와 차트 판은 컨테이너 폭(272)의 좁은 배치로 다시 그려진다. 눈으로 본 범위는 표현 범위의 표가 정한다. 선 굵기는 모든 계열이 같은 토큰이다
데스크톱 실제 크기 비교 없음 눈으로 본 범위는 표현 범위의 표가 정한다. 그 밖은 검증 요구사항, 미완료다
선택 면 없음 선택 면은 중립 면으로 둔다. 공식 기준과 일치한다는 근거가 아니다
확장 색 후보 없음 보라와 청록은 실제 크기 라이트·다크 목업 비교로 골랐다. 색각 이상 실제 사용자 시험은 검증 요구사항, 미완료다

색 역할

공통 색과 그림 전용 색은 공통 디자인 정본에서 관리한다. 기본 단계와 역할 토큰을 구분하며 코드와 CSS는 역할 토큰만 사용한다. ThinkFlow는 호스트 앱이 설치한 공통 패키지 하나를 peer 의존성으로 읽고 같은 토큰을 다시 정의하지 않는다. 설치된 패키지(@woonyong-choi/design-tokens)와 생성 토큰은 손으로 고치지 않는다. 수치는 라이트 정본과 다크 정본에서 확인하며 계산값 표를 문서에 복사하지 않는다.

독립 SVG는 배경, 공통 정의(defs), 정지·재생 층과 스타일을 모두 조립한 뒤 필요한 토큰과 그 의존성을 내장한다. HTML도 차트 움직임을 포함한 최종 스타일과 그림 틀을 조립한 뒤 토큰을 고른다. 토큰 사용량을 계산한 뒤 별도 스타일이나 마크업을 덧붙이지 않는다. 두 출력에 필수 변수 정의가 있는지는 test/exports.test.js의 renderers_embed_required_style_variables 시험으로 확인한다. 기본값이 있는 선택 변수와 실제 히트맵 칸이 공급하는 강도 변수는 해당 사용 조건을 함께 확인한다.

아래 표는 역할과 검사 기준만 기록한다. 대비는 그 요소가 실제로 그려지는 합성된 면과 역할(글자, 선, 면)마다 그 면 위에서 잰다. 기준은 의미를 전달하는 글자와 상태 표시에 적용하고, 장식 경계(color.help-border, color.ui-line, plate-border)에는 적용하지 않는다.

역할 뜻 검사 기준
state.active 활성 선·점·도형 테두리 3 이상
state.active-fill 선택한 면 on-active 글자 4.5 이상
state.active-text 활성 글자 4.5 이상
ui.link 링크 4.5 이상
ui.focus 키보드 초점 3 이상
figure.icon 도형 아이콘 면 위 대비를 역할마다 잰다. 낮은 값은 색을 바꾸지 않고 이름과 글자가 보완한다
data.main 주 계열 핵심 파랑 면, 구분은 이름과 직접 라벨
data.compare 비교 계열 핵심 노랑 면, 구분은 이름과 직접 라벨
ink 본문과 그림 글자 4.5 이상
ui-muted 보조 글자 4.5 이상
color.prose-pre-background 설명용 그림 판 글자 대비 기준 적용
ui-card 도형·카드 면과 문서 바탕 글자 대비 기준 적용
group-title 그룹 제목 4.5 이상
outline 대기열 칸의 윤곽과 대기 상태 알약의 테두리·기호 도형 면 위에서 3 이상. 알약은 WAIT 글자가 함께 간다
surface-edge 도형, 선 라벨 알약, 칩의 평소 경계 장식 경계라 대비 기준이 없다
line 연결선과 그룹 경계, 생명선 관계 선이라 면 위에서 재되, 못 맞춰도 색을 바꾸지 않고 번호와 선 라벨, 이름이 보완한다
plate-border 판과 조작부 구분선 1.3 이상
card-on 밝힌 칸과 테이블 열 줄의 활성 면(내용이 찬 카드는 중립이라 쓰지 않는다) 글자 대비 기준 적용
  • 색 하나로 뜻을 전하지 않는다. 이름, 글자, 윤곽이 함께 간다. 글자 4.5 기준은 낮추지 않는다.
  • 상태: 활성은 파랑, 주의는 노랑, 오류는 빨강, 정상은 초록이고 늘 아이콘과 글자가 함께 간다. 이 배정이 정본 값과 다르면 정본에서 고친다.
  • data.main, data.compare는 선언 순서가 아니라 계열의 role이 정한다(차트). 같은 계열 이름은 모든 예제에서 같은 역할이다.
  • 사이트 기능 아이콘 면색과 앱 범용 색은 구분한다. 핵심 넷의 값은 앞의 값이고, 앱의 각 역할이 같은 색이라고 주장하지 않는다.
  • 구성도 의미 아이콘은 작은 면 타일과 글리프이며 역할별 면과 윤곽을 갖는다. 이 역할 색은 공개 화면을 읽어 정한 해석이며 Things의 토큰이나 소스가 아니다.
  • 표 열의 PK, FK 표시는 항상 있는 스키마 표시라 color.ui-muted다. 칸 격자의 칸(칸 격자)은 새 색 역할이 없고 ui-card, color.ui-line, line, ink, surface, ui-muted, card-on, state.active의 기존 짝을 쓴다.
  • 설명 판은 color.prose-pre-background, 도형·카드 면과 문서 바탕은 color.ui-card를 쓴다. 그룹은 면 없이 경계와 제목으로 구분하며, appearance=filled로 고른 그룹만 color.paint.<이름>.fill 면을 쓴다. 중첩 깊이에 따라 면색을 바꾸지 않는다. 이름과 면으로 경계가 식별되는 도형에는 color.help-border 장식선을 쓰고, 의미를 전달하는 선에는 대비 3 이상의 역할색을 쓴다. 내부 표와 배지는 color.ui-line 한 규칙을 공유한다. 박스플롯의 중앙값·수염 같은 데이터 선은 color.figure-data-line으로 구분한다.
  • 색을 고른 도형은 재생 중에도 색 역할을 유지한다. 도형 외곽선은 1px, 색을 지정한 그룹은 1.5px로 유지하고 후광용 복제 윤곽을 그리지 않는다. 색을 지정하지 않은 도형의 활성 상태는 같은 굵기의 파란 외곽선이다. 선택 칸은 color.search-hover 면과 같은 모서리의 단일 선이다.
  • 태그 글자는 color.ink이고 범주색은 글자 뒤의 옅은 바탕 띠로만 전한다. 태그 색은 갈래를 나누는 색이고 판정을 뜻하지 않는다.
  • 범주 토큰은 design-tokens가 계열마다 원색(color.category.<계열>.anchor)에서 계산한다. color.data.category-family.N이 기록한 순서이고 color.data.category.N(면, 두 모드 같은 원색), category-outline.N(테두리), category-on.N(면 위 글자), category-ink.N(같은 계열 글자색, 못 맞추면 ink), category-tint.N(옅은 면), category-label.N(required이면 직접 라벨)이 번호로 따른다. 코드는 번호 토큰만 읽고 src/chart-palette.js의 categoryPaint(index)가 계열, 면, 테두리, 위 글자, 층(tier), 무늬, 간격, 모양, needsLabel을 한 번에 준다. 번호가 색 수를 넘으면 계열이 순환하고 층이 오르며 무늬(category-pattern.N)는 층 1부터, 모양(category-shape.N)은 층과 상관없이 범주 번호마다 고정된 순서로 바뀐다(번호를 모양 개수로 나눈 나머지). 색·무늬·모양 목록은 뒤에만 늘어나고, 늘면 순환 길이가 바뀌어 기존 범주의 칠이 달라지므로 칠은 판(color.data.category-revision.N.{family,pattern,shape,step})으로 고정한다. 판 N은 세 목록의 앞쪽 개수와 무늬 간격 배율 step을 가진 숫자 토큰이고, categoryPaint(index, { revision })의 기본은 최신 판이 아니라 언제나 1판(일곱 계열, 무늬 3, 모양 4, step 0.5)이다. 덧붙인 색은 소스가 더 높은 판을 명시할 때만 쓰이고, 판을 고르는 소스 문법은 2판을 더하는 변경에서 함께 넣는다. 무늬 간격의 기준은 spacing.figure.chart.pattern-spacing(8), 무늬 선 굵기는 border-width.tag이며 SVG 무늬 정의는 렌더러가 만든다.
  • 상태 색(state.*)은 범주 번호와 무관하게 고정된 계열의 테두리를 가리킨다. 상태가 있거나 없다고 범주의 순서가 바뀌지 않는다.

원본이 고르는 색 이름

원본이 직접 고르는 색 이름(흐름과 도형, 그룹, show 줄의 tone)은 핵심 넷과 확장 순서를 따른 팔레트 계열 일곱(blue, yellow, red, green, orange, purple, cyan)과 무채색 gray다. 이름이 없는 점과 태그는 같은 순서로 색을 받는다(src/tone.js). 이전 체계의 이름과 별칭은 읽지 않는다. 차트 계열 수에는 상한이 없고 색 수를 넘는 계열은 위 색 계약의 무늬·모양·직접 라벨로 구분한다. 흐려진 행의 대비를 3으로 맞추라고 요구하지 않고, 면 위 대비가 낮은 표식은 색을 바꾸지 않고 라벨이나 모양으로 보완한다(차트).

색표와 글꼴

  • 모든 그림의 SVG width는 같은 표준 캔버스 폭(spacing.figure.figure-canvas, 960)이다. 그림 머리 width wide를 쓴 그림만 넓은 폭(spacing.figure.figure-canvas-wide)이고, 문서에서는 본문 폭에 맞춰 줄어든다. 가운데 정렬은 SVG 파일이 아니라 문서 쪽 몫이다. GitHub README는 <p align="center"><img src="docs/assets/그림.svg" alt="설명"></p> 형식으로 넣어야 가운데에 선다(Markdown 이미지 문법으로는 정렬할 수 없다).
  • 글꼴은 이 도구가 Pretendard, JetBrains Mono 파일(수학 기호용 Noto Sans, Noto Sans Math 포함)을 함께 배포하고 그림에 잘라 넣는다. 본문 글자 간격은 tracking.text(-0.3px)다(배치). 스킬의 글꼴 설치 줄은 지운다.
  • HTML 페이지와 조작부는 font.sans의 시스템 글꼴, HTML 코드와 파일 이름은 font.mono를 쓴다. SVG 내부만 측정한 FigSans·FigMono 조각을 내장해 배치와 표시 폭을 일치시킨다. 글자 위계와 크기는 배치의 글꼴 자리를 따른다. 페이지 큰 제목은 목록과 문서 모두 36px·700·줄 높이 1.2다.

조작과 선

장면 탭과 테마 선택은 공통 TabList의 크기·여백 규칙을 사용한다. 선택·pressed·focus는 조작부의 공통 조작 역할 토큰을 쓴다. 좁은 화면에서는 탭이 줄바꿈하며 그림은 자연 크기를 유지하고 남는 가로 부분을 그림 영역 안에서 스크롤한다. 페이지 전체에는 가로 스크롤을 만들지 않는다. 켜진 탭은 color.feature-tab-selected 면과 segment-on-ink 글자로만 구분하고 테두리 고리를 더하지 않는다. 켜진 탭 글자와 면의 대비는 이 문서가 보증하지 않는다(검증 요구사항, 미완료). 재생기에는 재생, 일시정지, 배속, 반복 조작이 없고 조작은 장면 탭과 도구 막대(재생)뿐이다. 도구 막대는 Things에 대응 요소가 없는 확장이다. 모양과 크기를 이번 개편 뒤 실제 화면에서 보는 검수와 실제 기기에서 눌러 보는 검수는 하지 않았다(검증 요구사항, 미완료).

카드는 반지름 18px의 흰 표면과 두 겹 그림자(shadow.diagram)를 쓴다. 도형은 그림자 없는 평면이고 그림자는 떠 있는 조작에만 쓴다. 목록 폭은 960px, 카드 사이는 48px다.

선 굵기는 역할마다 토큰 하나다. 도형 윤곽은 border-width.thin, 칩과 카드 안 틀, 격자 칸, 표 구분선과 판 안 경계는 border-width.thin과 border-width.hair, 관계(연결선과 카드 안 관계 그래프 선)는 border-width.edge, 생명선은 border-width.lifeline, 색을 지정한 그룹의 윤곽은 border-width.tag이고 차트 표식은 차트가 정한다(차트). 지금 단계는 선 굵기를 바꾸지 않고 색이나 면만 바꾼다. 유일한 예외는 키보드 초점(:focus-visible)으로, 도형 자신의 윤곽을 outline-width.focus와 --color-ui-focus로 그린다. 모든 선은 그림과 함께 같은 비율로 커지고 줄어든다. 전체화면 맞춤에서 줄어든 선의 눈 검수는 이번 개편 뒤 하지 않았다(증거 표, 검증 요구사항, 미완료). 끝과 이음은 둥글다.

대비 기준

대비는 그 요소가 실제로 그려지는 면과 역할(글자, 선, 면)마다 그 면 위에서 라이트와 다크 모두 잰다. 기준은 토큰 정본에서 풀어 재고, 이를 자동으로 다시 재는 시험은 지금 없다(검증 요구사항, 미완료). 핵심 색과 카테고리 면색(핵심 넷과 확장)은 값을 바꾸지 않으므로 면 자체에 일률 그래픽 대비를 요구하지 않고, 뜻은 이름·직접 라벨·무늬·모양이 함께 전한다. 기준에 못 미치는 그래픽은 색을 바꿔 맞추지 않고, 장식 경계는 대비 기준이 없으며, 낮은 대비를 접근성 기준 충족이라고 쓰지 않는다.

쌍 기준 근거
본문 글자(ink), 보조 글자(ui-muted)와 모든 면(color.prose-pre-background, ui-card, surface, card-on) 4.5 이상 WCAG 글자 기준
강조 글자(state.active-text: 링크, 카드 표시 ✓)와 그림 바탕, 노드, 카드 바탕, 문서 바탕 4.5 이상 같음
강조 UI 그래픽(state.active: 밝힌 선, 점, 테두리)과 그림 바탕, 그룹 바탕, 카드 바탕, 노드, 문서 바탕 3 이상 WCAG 그래픽 기준
키보드 초점 고리(ui.focus)와 그림 바탕, 카드 바탕, 문서 바탕 3 이상 같음
state.on-active 글자와 state.active-fill 면 4.5 이상 같음
면 위 글자(on)와 카테고리 면 4.5 이상이면 글자를 놓고, 못 미치면 글리프만 놓고 글자는 면 밖에 둔다 검은색과 흰색 중 대비가 큰 쪽을 계산해 고른다
카드 태그 글자(ink)와 어느 톤 띠 4.5 이상 같음
밝히지 않은 행(ink.dim, opacity.dim-ink)의 ink, ui-muted 글자와 bg 4.5 이상 같음
대기열 칸의 윤곽과 대기 알약의 테두리·기호(outline)와 도형, 카드 바탕 3 이상 상태를 전하는 그래픽. 자동 시험은 지금 없다(검증 요구사항, 미완료)
도형의 평소 경계(color.help-border), 표와 칩의 구분선(color.ui-line) 기준 없음 장식 경계라 진하게 바꾸지 않는다. 도형은 이름과 면이 식별한다
그룹 제목(group-title)과 실제 그룹 바탕 4.5 이상 같음
히트맵 칸 숫자와 그 칸 색 4.5 이상 칸마다 어두운 글자와 밝은 글자 중 대비가 큰 쪽을 빌드 때 고른다
차이 차트의 0선, 행 기준 점선, 잘린 축의 지그재그(ui-muted)와 그림 바탕 4.5 이상 값 차이를 전하는 그래픽이라 ui-muted의 글자 기준을 쓴다
꾸밈 요소: 격자와 축, 히트맵 값 0 칸, 신뢰구간 띠와 덤벨 범위 막대기 1.5 이상 WCAG 적용 대상 밖이다. 값은 숫자로도 적히고 이 요소는 구조만 돕는다
꾸밈 요소: 판 테두리(plate-border)와 문서 바탕(ui-card) 1.3 이상 WCAG 적용 대상 밖이다. 판 모양만 잡고 판 안 도형은 각자 3을 맞춘다

변환과 검사

스킬 규칙 이 도구
변환은 render_figures로만 render_figures가 .thinkflow 원본마다 thinkflow render --strict를 부른다. 경고도 실패다
실험 차트의 자료 출처와 신뢰구간 문서 작성 과정에서 확인한다. ThinkFlow는 inline 행과 외부 JSON의 값·구간 유효성을 검사한다(차트)
원본과 만든 그림 함께 커밋 그대로
변환 뒤 그림을 열어 겹침, 잘림, 빈 영역 확인 그림 검사는 겹침과 잘림의 자동 증거를 낸다. 눈 확인을 대신하지 않으며 빈 영역은 검사 항목이 없다
다시 변환 뒤 git diff 없음 배치의 결정성 요구사항이 지킨다
원본에 색, config, sketch 없음 색 줄과 hex는 문법에 없다. 도형 색은 팔레트 이름 tone=과 appearance=만 받아 검사 항목에서 지운다
  • 결과는 움직이는 SVG {이름}.svg 하나다. 무엇이 언제 움직이는지는 재생을 따른다. HTML 재생기는 문서 저장소에 넣지 않는다. 문서 저장소에 스크립트가 든 파일을 늘리지 않기 위해서다.
  • npm run check는 토큰 생성물 최신 여부, 재정의, 하드코딩을 실패로 지키는 정확성 관문이다. 파일 300줄, 함수 40줄, 매개변수 3개, 비용 주석 누락은 npm run check:advisory가 알리기만 한다. 두 검사는 줄 단위 정규식이라 여러 줄 매개변수 목록이나 블록 주석 안의 중괄호를 바르게 읽지 못하고, 수치를 맞추려고 일관된 코드를 쪼개거나 근거 없는 점근 표기를 적게 만들기 때문이다. 실행 오류(없는 경로, 잘못된 옵션)는 이 명령도 종료 코드 2로 실패한다.

바꾸는 순서

  1. 이 도구가 스킬의 다섯 그림(맥락, 구성 요소, 순서, 상태, 데이터)과 스킬이 쓰는 차트 종류를 구현하고, 모든 예제가 그림 검사를 통과한다.
  2. repo-docs-figures 스킬의 도구 표, 색표, D2 절, Vega-Lite 절을 이 도구 기준으로 다시 쓰고, render_figures에 .thinkflow 변환을 넣는다.
  3. 스킬 저장소의 형식 검사가 total 0이 된 뒤 skill-sync로 설치한다.
  4. 문서 저장소마다 docs/assets/*.d2와 *.vl.json을 .thinkflow로 옮기고 다시 변환한다. 옮긴 뒤 D2와 Vega-Lite 변환 분기를 지운다.
  • 1번이 끝나기 전에 스킬을 바꾸지 않는다. 없는 도구를 쓰라고 적는 스킬은 스킬의 정직한 상태 규칙을 어기기 때문이다.
  • 원본의 첫 비주석 의미 줄은 숫자나 옵션 없는 thinkflow다. 시작 선언이 없거나 잘못되면 줄 위치와 함께 오류다. 읽는 어댑터와 옛 이름 전용 경로는 없고 읽는 확장자는 .thinkflow뿐이다. 스킬의 변환 명령은 thinkflow만 부른다.

요구사항

요구사항 검증 계획
스킬의 다섯 그림 템플릿을 새 문법으로 옮긴 원본이 검사를 통과한다. 템플릿마다 원본을 만들어 check 실행
스킬의 차트를 data 줄로 그린다. 예시 summary.json으로 차트별 원본 변환
같은 원본을 다시 변환해도 git 차이가 없다. 두 번 변환 뒤 git diff 확인
확장 색 후보를 실제 크기 라이트·다크 구성 요소로 비교해 고른다. 후보 비교 화면 검수. 팔레트 개정 1의 채택 기록은 소유 저장소 tokens/tokens.json의 review에 있고, 제품 화면에서 확인한 범위는 표현 범위가 정한다. 색각 이상 실제 사용자 시험은 검증 요구사항, 미완료
공식 Things 기준과 화면 비교를 마친다. 수용 게이트(모바일 320·390·430px, 데스크톱 실제 크기, 라이트·다크, 정지·재생). 확인한 범위는 표현 범위가 정하고 그 밖은 검증 요구사항, 미완료. 공식 이미지와의 비교는 역할 비교이며 현재 네이티브 앱 전체와의 픽셀 대조가 아니다

단점

  • 문서 저장소의 기존 D2, Vega-Lite 원본을 모두 다시 써야 한다.
  • 스킬이 이 도구의 배포 방법(npm 패키지나 저장소 경로)에 묶인다.

미해결 질문

  • 이 도구를 스킬 안 스크립트처럼 스킬 폴더에 넣나, npm 패키지로 배포하나.