모델 지원 문서화에서 가장 유용한 분리는 산문(prose) 대 코드(code)가 아니라, 사실(facts) 대 문장(sentences)입니다. 모델이 기본값이나 플래그 이름 같은 것을 재진술하도록 허용할 경우, 잘못된 답변은 검토 시점에서는 올바른 답변과 구별하기 어려워집니다. 아래 워크플로우는 모든 검증 가능한 값은 수집기 스크립트(collector script)에 맡기고, 모든 연결 문장(connective sentence)은 초안 작성 모델(drafting model)에 맡깁니다. 사실들은 체크인된 아티팩트(artifact)에서 렌더링 시점에 주입되므로, 산문이 물리적으로 이를 생성할 수는 없습니다.
본 글의 나머지 부분을 정직하게 유지하기 위해 두 가지 정의를 명확히 합니다. '사실(Facts)'이란 소스 코드로부터 도출될 수 있는 모든 것을 의미합니다: 옵션 이름, 기본값, 필수 여부, 엔드포인트 경로, 열거형 멤버(enum members), 그리고 하드 리밋(hard limits) 등이 포함됩니다. '문장(Sentences)'이란 이러한 값들을 둘러싼 설명이며, 이는 재생성이 쉽지만 미묘한 방식으로 틀리는 것이 비용이 많이 듭니다.
모델이 초안을 작성할 수 있는 것과 인간이 소유해야 하는 것
소유권 표는 이 전체 디자인을 행(row)으로 압축한 것입니다. 기계적인 출처를 가진 것은 키(key)를 부여받고, 의도(intent)가 필요한 것은 이름(name)을 받습니다.
| 콘텐츠 | 소유자 | 이유 |
|---|
| 옵션 이름, 기본값, 필수 여부 | 수집기 스크립트 (collector script) | 매 커밋마다 소스에서 재도출 가능 |
| ... | | |
제 논의 워크플로우에서는 세 가지 항목(근거/rationale, 마이그레이션 가이드(migration guidance), 주의사항(caveats))은 협상 불가능합니다. 모델이 이들에 대한 문장을 제안할 수는 있지만, 이름이 지정된 인간이 병합된 버전(merged version)에 서명해야 합니다.
1단계 — 소스로부터 사실 아티팩트 도출하기
먼저 검증 가능한 값들을 단락(paragraph)이 아닌 빌드 출력으로 만듭니다. 아래의 수집기는 템플릿이며, 셸아웃(shell-out) 부분을 사용 중인 CLI의 도움말 출력, OpenAPI 파일 또는 설정 스키마 로더로 교체하십시오.
# collect_facts.py — 기계적으로 도출 가능한 값을 JSON으로 방출
import json, subprocess, sys
...
이를 추적되는 파일에 실행하고 다른 코드 변경사항처럼 diff를 검토합니다:
python collect_facts.py > facts/facts.json
python -m json.tool facts/facts.json | head -20
git diff --stat facts/facts.json
수집된 diff가 비어 있다면, 문서 참조는 법적으로 변경될 수 없습니다. 이 속성만으로도 모델이 개입하기 전에 대규모의 오래된 값(stale-value) 버그 클래스를 제거할 수 있습니다.
2단계 — 각 페이지를 프래그먼트와 필수 키로 선언하기
페이지 이름, 산문 프래그먼트, 그리고 해당 페이지가 다루어야 할 사실(fact) 키를 명시하는 작은 매니페스트(manifest)를 유지합니다. 이 매니페스트는 가드 테스트(guard test)가 반복 검사하는 대상이므로, 설계상 간결하게 유지됩니다.
{"pages": [{"name": "cli-reference", "fragments": ["intro", "options"], "required_keys": ["cli.output.flag", "cli.verbose.default"]}]}
산문 프래그먼트(Prose fragments)는 값 대신 플레이스홀더(placeholders)를 포함합니다. 아래의 프래그먼트는 기본값을 명시하지 않으며, 단지 기본값이 실제로 무엇을 의미하는지만 설명한다는 점에 유의하십시오.
### --{{fact:cli.output.flag}}
플래그를 {{fact:cli.output.default}}로 설정하면 기계가 읽을 수 있는 출력을 작성합니다.
...
3단계 — 초안 모델(drafting model)을 플레이스홀더로만 제한하기
초안 모델에게 모방할 예시 대신 계약서(contract)를 제공해야 합니다. 제 계약은 세 가지 조항으로 구성되어 있으며, 세 번째 조항이 파이프라인이 조용히 실패하는 것이 아니라 명확하게(loudly) 실패하도록 만듭니다.
- 모든 값에 대해
{{fact:...}} 토큰을 사용하고; 플래그 이름, 기본값 또는 제한을 문자 그대로 타이핑하지 마십시오.
- 필요한 값이 키를 가지고 있지 않다면,
{{fact:MISSING:describe_what_you_need}}를 방출하고 해당 섹션을 중단하십시오.
- 경고, 마이그레이션 조언 또는 버전 주장을 추가하지 마십시오. 그것들은 사람이 작성한 슬롯입니다.
초안 단계는 일회성 모델 출력(disposable model output)이 가장 도움이 되는 부분인데, 거부된 프래그먼트는 재실행 비용만 발생할 뿐 다른 비용은 들지 않기 때문입니다. 저는 해당 프래그먼트들을 MonkeyCode의 무료 모델 액세스를 통해 실행하는데, 운영자(operator)에 따르면 이는 유료 없이 이용 가능하다고 하므로, 문구 변경 후 단락을 재생성하는 것이 예산 결정 사항이 아닙니다. 공개: 이 기사는 MonkeyCode의 제품 홍보 활동의 일환으로 준비되었습니다.
4단계 — 페이지를 렌더링하고 보호하기(Render and guard the page)
렌더러(renderer)는 플레이스홀더를 해결하고, 미해결 키가 있는 페이지는 발행하는 것을 거부합니다. 치환 실패는 한 번의 실행에서 모든 깨진 키를 볼 수 있도록 먼저 수집됩니다.
# render_docs.py
import json, pathlib, re, sys
...
아티팩트(artifact)의 후반부는 누수 테스트(leak test)입니다. 이는 플레이스홀더를 제거한 다음, 산문(prose)에 실제 사실 값이 남아 있지 않은지 검증하며, 이는 '모델이 값을 생성해서는 안 된다'는 것의 기계적인 버전입니다.
# tests/test_docs_facts.py
import json, pathlib, re, pytest
...
드리프트(drift)를 리뷰어가 아닌 가드(guard)가 포착하도록 전체 루프를 하나의 명령으로 실행합니다:
python collect_facts.py > facts/facts.json && python render_docs.py && pytest tests/test_docs_facts.py -q
단계 5 — 네 가지 질문으로 인간의 게이트 유지하기
자동화는 검토 표면적을 줄이지만 결코 제거하지는 못합니다. 다음 네 가지 질문은 누수 테스트를 통과하는 거의 모든 조각(fragment)을 다룹니다.
- 어떤 문장이 대응하는 사실 키나 테스트된 예제가 없는 행동을 단언하고 있습니까?
- 해당 조각이 프로젝트가 보장하지 않는 조언, 버전 이름 또는 안정성을 약속합니까?
- 모든 펜스 처리된 예제(fenced example)가 산문에 타이핑된 것이 아니라 CI에서 실행되는 파일에 고정되어 있습니까?
- 이 페이지의 근거(rationale), 마이그레이션(migration), 그리고 주의 사항 문장은 누가 서명합니까?
두 번째 질문에 실패한 조각은 수정되지 않고, 삭제되어 인간이 소유권을 가진 슬롯으로 다시 작성됩니다. 이는 모델의 기여를 연결 조직(connective tissue)으로 유지하고 책임 소재를 개인에게 붙잡아 둡니다.
제한 사항 및 사용해서는 안 되는 경우
이 접근 방식은 사실(facts)에 대해 기계가 읽을 수 있는 출처(machine-readable source)가 존재하는 경우에만 효과적입니다. 설계 근거(Design Rationale), 튜토리얼, 사후 분석 보고서(Postmortems), 아키텍처 설명(architecture narratives) 등에는 수집기(collector)가 없으므로, 파이프라인은 값비싼 산문 저장소로 축소됩니다. 누출 테스트(leak test) 역시 어휘적입니다. 예를 들어 “질문하지 않으면 비활성화됨(disabled unless you ask)”과 같은 의역된 사실은 기본값을 여전히 명시하면서도 통과할 수 있습니다. 세 글자 미만의 짧은 사실 값들은 일반 단어들과 너무 자주 충돌하여 위에서 제시한 허용 목록(allowlist)이 필요합니다. 마지막으로, 이 수집기는 이제 사용자가 유지 관리해야 하는 코드이며, 조용히 고장 난 수집기는 자신감 있게 잘못된 페이지를 생성합니다.
팀에 옵션 값에 대한 단일 진실 공급원(single source of truth)이 없거나 문서가 참고 자료라기보다는 설득에 치중하는 경우라면 이 워크플로우는 건너뛰십시오. 또한, 안정적인 플래그가 네 개 정도인 매우 작은 표면적(surfaces)의 경우에는 수동으로 검토된 일반 Markdown 파일이 렌더링 단계와 가드(guard)를 거치는 것보다 저렴합니다.
파이프라인을 변경하지 않고도 초안 작성 절반(drafting half)을 테스트하고 싶다면, 먼저 로컬에서 1단계와 4단계를 실행한 후 사실 아티팩트가 깨끗해질 때까지 모델은 사용하지 마십시오. 무료 모델 접근 및 무료 서버 옵션은 반복적인 조각 재작성(fragment redrafts)과 공유 환경에서 수집-렌더링-테스트 루프를 유지하는 데 유용하지만, 어느 것도 소유권 테이블(ownership table)을 대체할 수는 없습니다. 모델부터 시작하지 말고, 테이블부터 시작하면 나머지 빌드는 따라옵니다.