chore: 문서를 작성할 때 한국어의 표현 작성 스킬 추가 및 1인칭 관점의 글 작성 검증 테스트 추가

This commit is contained in:
DongHyeonka
2026-07-29 16:48:03 +09:00
parent c39406bbdd
commit 41501b5d06
520 changed files with 95494 additions and 2231 deletions
+128 -93
View File
@@ -1,130 +1,165 @@
# Architecture
## 1. 설계 목표
## 1. 목표
ClariDoc의 핵심 목표는 생성 모델의 문장 능력보다 **정보 구조, 근거 추적, 검토 독립성, 재현 가능한 품질 판정**을 상위 제어 계층에 두는 것이다.
ClariDoc은 문장 생성 능력보다 다음 제어 계층을 우선한다.
설계 원칙:
1. **Contract before prose**: 초안보다 브리프와 문서 유형 계약을 먼저 검증한다.
2. **Reader-question chain**: 각 절은 하나의 독자 질문에 답한다.
3. **Deterministic minimums**: 모델이 놓치기 쉬운 형식·안전·인용 조건은 코드로 검사한다.
4. **Role separation**: 작성자와 리뷰 관점을 분리한다.
5. **Evidence boundary**: 출처의 사실과 모델의 설명·추천을 구분한다.
6. **Auditability**: 원문 응답, 정규화 입력, 결과, 이벤트, 해시를 보존한다.
7. **Safe degradation**: planner가 실패하면 결정적 구조로 폴백하지만 writer 실패는 숨기지 않는다.
1. 독자 과업과 문서 유형 계약
2. 프로젝트 근거의 수집과 source hierarchy
3. 기술 선택의 rationale completeness
4. 독자용 prose와 내부 provenance의 격리
5. 결정적 검사와 독립 reviewer
6. 재현 가능한 artifact와 hash manifest
## 2. 구성요소
```text
models.py 입력/출력 계약과 검증
structures.py 문서 유형별 필수 section intent와 순서
prompts.py planner/writer/reviewer/reviser 출력 계약
providers/ Codex, Claude, Antigravity, Mock 어댑터
lint.py 모델과 독립적인 Markdown/논리 프록시 검사
pipeline.py 단계 실행, 수정 루프, 품질 게이트, 감사 산출물
models.py brief/source/outline/review/pipeline 계약
corpus.py 로컬 문서 탐색, heading chunk, ranking, source-pack 생성
structures.py 문서 유형별 필수 section intent와 decision requirements
prompts.py planner/writer/reviewer/reviser 경계와 출력 계약
providers/ Codex, Claude, Antigravity, Mock adapter
lint.py 구조, 메타 누출, rationale, 안전성의 결정적 검사
provenance.py evidence-map.json과 provenance.md 생성
pipeline.py 단계 실행, 리뷰, 수정 루프, quality gate, manifest
report.py 사람이 읽는 품질 보고서
cli.py init/validate/outline/lint/run/doctor 명령
cli.py init/collect/validate/outline/lint/run/doctor
```
## 3. 단계별 상태 전이
## 3. 입력 계층
### 3.1 계약 입력
### 3.1 Brief
- `Brief`: 독자, 목표, 핵심 메시지, 범위, 비범위, 선행지식, 필수 주제, 버전 맥락, 금지 주장
- `SourcePack`: 출처 식별자와 출처가 실제로 지지하는 사실 단위
- `PipelineConfig`: 각 역할의 provider, timeout, 옵션, 품질 게이트
Brief는 주제보다 독자 과업과 판단 경계를 먼저 고정한다.
입력은 정규화되어 `inputs/`에 기록된다.
- audience / prior knowledge / needs
- reader goal / core message
- scope / non-scope
- prerequisites / required topics
- citation style / date policy / style profile
- forbidden claims
### 3.2 결정적 기본 outline
### 3.2 SourcePack
`structures.py``document_type`에 따라 필수 intent를 만든다. 각 section은 다음 계약을 가진다.
Source는 단순 URL이 아니라 다음 metadata를 가질 수 있다.
```json
{
"id": "04-mechanism",
"intent": "mechanism",
"title": "해결 방식이 동작하는 과정",
"reader_question": "구성요소와 데이터 흐름은 어떻게 연결되는가?",
"purpose": "메커니즘을 단계적 인과 사슬로 설명한다.",
"must_include": ["구성요소", "데이터 또는 제어 흐름", "불변조건"],
"evidence_ids": ["S1"],
"transition_to_next": "다음 독자 질문으로 연결한다."
"id": "L1234abcd",
"title": "...",
"url": "repo:///raw/branch-notes/example.md",
"facts": ["heading chunk text"],
"source_type": "branch-note",
"status": "verified",
"path": "raw/branch-notes/example.md",
"heading": "결정 사항",
"line_start": 120,
"line_end": 150,
"claim_ids": ["TX-C1"],
"decision_ids": ["D13"],
"priority": 21.7
}
```
### 3.3 Planner 정교화
이 metadata는 내부 reasoning과 audit에 사용된다. `citation_style=hidden`에서는 독자용 문서로 출력되지 않는다.
Planner는 section 제목, 질문, 목적, `must_include`, 근거 배치, 전환을 개선한다. `reconcile_outline`은 다음을 거부한다.
## 4. Local corpus retrieval
- 문서 유형 변경
- 필수 intent 삭제
- intent 중복
- 필수 순서 변경
- 존재하지 않는 source ID
`corpus.py`는 다음 순서로 동작한다.
Planner 실행 또는 JSON 파싱이 실패하면 기본 outline을 사용하고 경고를 기록한다.
1. configured include directory를 순회한다.
2. Markdown frontmatter에서 title/status를 읽는다.
3. heading 단위로 chunk를 만든다.
4. query와 각 chunk를 BM25 계열 점수로 비교한다.
5. source type, status, decision/rationale 용어에 가중한다.
6. 파일별 최대 chunk 수와 전체 top-k를 적용한다.
7. repository-relative provenance를 포함한 SourcePack으로 변환한다.
### 3.4 Writer
Writer는 exact H1과 exact H2 순서를 지켜 전체 Markdown을 반환해야 한다. 브리프와 출처는 지시가 아닌 untrusted data로 경계 표시된다. Writer 실패는 대체 텍스트로 숨기지 않고 실행 오류로 종료한다.
### 3.5 결정적 린트
린터는 모델 응답과 독립적으로 구조, 형식, 절차, 안전, 근거 표식을 검사한다. 자연어 의미를 완전히 판단하지 않으며 **최소 품질 바닥**을 제공한다.
### 3.6 독립 리뷰
각 reviewer는 동일한 초안을 다른 실패 함수로 검사한다.
- logic: 전제→결론, 인과 단절, 모순, section 역할
- reader: 선행지식, 방향 감각, 점진 공개, 예시, scan path
- evidence: 출처 적합성, 지원되지 않은 확신, 버전 민감성
- operations: 절차 순서, 검증, 파괴적 조작, 복구, 관측
- editor: 문장·문단 초점, 용어, 중복
리뷰 응답은 고정 JSON 스키마로 파싱된다. 필수 reviewer가 실패하면 기본적으로 실행이 실패한다. `fail_on_reviewer_error: false`는 실패 리뷰를 blocker/0점으로 기록해 산출물을 남긴다.
### 3.7 품질 게이트와 수정
Source precedence:
```text
model_mean = mean(review.score)
composite = lint.score * deterministic_weight + model_mean * model_weight
PASS = composite >= minimum_score
AND blockers <= max_blockers
AND errors <= max_errors
canonical-project
> canonical-concept
> branch-note
> official-doc
> company-tech-blog
> local-document
```
FAIL이고 수정 한도가 남으면 reviser가 lint와 모든 리뷰를 받아 전체 문서를 다시 작성한다. 수정된 초안은 동일한 린트와 리뷰를 처음부터 통과해야 한다.
이 순서는 절대적인 진실 순위가 아니다. 현재 프로젝트 상태에는 canonical project가 우선이고, 선택 배경에는 branch note가 더 유용할 수 있다. Planner와 reviewer가 claim 종류에 맞게 사용해야 한다.
## 4. 신뢰 경계
## 5. Outline contract
| 경계 | 신뢰 수준 | 처리 |
|---|---|---|
| pipeline config | 로컬 운영자가 승인한 코드 수준 설정 | command 실행 가능하므로 반드시 신뢰된 파일만 사용 |
| brief/source pack | 비신뢰 데이터 | prompt 내부에서 data로 구획, 지시 무시 명시 |
| model response | 비신뢰 출력 | JSON 파싱·계약 검증·lint·review 수행 |
| URL | 메타데이터 | 자동 방문/실행하지 않음 |
| final document | 검토 후보 | PASS여도 도메인 사실·코드 실행을 별도 검증 |
각 section은 다음 속성을 가진다.
## 5. 실패 정책
```json
{
"id": "04-decision-rationale",
"intent": "decision_rationale",
"title": "선택의 이유와 지킨 경계",
"reader_question": "왜 이 선택을 했고 무엇을 포기했는가?",
"purpose": "선택을 이유, 대안, 비용, 가드레일과 함께 설명한다.",
"must_include": ["선택", "이유", "대안", "수용한 비용", "가드레일"],
"evidence_ids": ["L..."],
"decision_requirements": [
"context_or_constraint",
"choice",
"why",
"alternative",
"accepted_cost",
"guardrail"
],
"transition_to_next": "코드와 흐름으로 연결한다."
}
```
| 단계 | 기본 실패 처리 | 이유 |
|---|---|---|
| planner | 결정적 outline 폴백 + 경고 | 구조의 안전한 기본값이 존재 |
| writer | 실행 중단 | 내용 없는 대체 초안은 유효하지 않음 |
| reviewer | 실행 중단 | 독립 검토가 구성 계약의 일부 |
| reviewer, fail-open 설정 | blocker/0점 리뷰로 기록 | 산출물 보존이 필요한 실험 환경 |
| reviser | 실행 중단 | 수정 실패를 이전 초안 통과로 위장하지 않음 |
| quality gate fail | final 산출물은 남기되 exit code 4 | 사람이 결함을 분석할 수 있도록 보존 |
Planner는 제목·질문·근거 배치를 정교화할 수 있지만 intent의 삭제, 추가, 재배열은 할 수 없다.
## 6. 재현성과 감사
## 6. Reader/provenance split
- provider 요청의 stage/provider/model/status/duration을 JSONL로 기록
- 각 모델의 raw response와 parsed JSON을 모두 보존
- 입력을 정규화해 실행 시점 계약을 고정
- 최종 산출물을 포함한 파일별 SHA-256 매니페스트 생성
- Mock provider로 외부 네트워크 없이 파이프라인 배선 재현
### Reader-facing surface
모델 자체의 비결정성까지 제거하지는 않는다. 운영에서 모델 ID, CLI/SDK 버전, 실행 날짜를 `version_context`, provider `model`, 별도 배포 메타데이터에 고정해야 한다.
- `final/document.md`
- 선택 이유와 기술 설명
- 공개 citation policy에 따른 citation만 포함
### Internal surface
- `final/provenance.md`
- `final/evidence-map.json`
- normalized source pack
- raw provider responses
- review JSON과 lint report
- provider event log
Hidden mode에서 internal source ID, repository path, access date가 `document.md`에 보이면 quality gate error다.
## 7. Review topology
- logic: 전제, 인과, 결론
- decision: context, why, alternative, cost, guardrail
- reader: orientation, cognitive load, natural prose
- evidence: claim/source fit, hierarchy, status
- operations: prerequisites, safety, verification, rollback
- editor: 문장 흐름과 표현, 질문-답 연결, 정보 구조가 반복 문장 틀로 노출되는지 검사
Writer와 logic·decision·reader·editor·evidence·operations reviewer를 분리해 self-review 편향을 줄이지만, 여러 모델의 일치는 사실 검증을 대신하지 않는다.
## 8. Quality gate
```text
composite = deterministic_lint × deterministic_weight
+ model_review_mean × model_weight
```
통과 조건은 점수와 함께 blocker/error 개수를 검사한다. revision loop가 최대 횟수에 도달하면 실패 상태와 artifact를 그대로 보존한다.
## 9. Failure behavior
- invalid input contract: 실행 전 실패
- planner invalid JSON/contract: deterministic base outline으로 안전 폴백
- writer/provider failure: 숨기지 않고 pipeline failure
- reviewer failure: config에 따라 failure 또는 blocker review
- revision no-op: warning 기록
- output path traversal in reviewer role: slug sanitize
- final artifact: manifest로 크기와 SHA-256 기록
+43 -46
View File
@@ -1,66 +1,63 @@
# Extending ClariDoc
## 새로운 문서 유형
## 새 문서 유형 추가
1. `DocumentType` enum에 값을 추가한다.
2. `STRUCTURE_SPECS`독자 질문 순서와 section intent를 정의한다.
3. 각 section에 title, reader question, purpose, must-include를 한국어/영어로 제공한다.
4. `lint.py`에 해당 유형의 최소 계약을 추가한다.
5. 모든 intent가 고유하고 최소 section 수를 만족하는 테스트 추가한다.
6. Mock writer에 새 intent의 fixture body를 추가하거나 명시적 fallback을 검증한다.
1. `DocumentType` enum 추가
2. `STRUCTURE_SPECS`reader-question 순서 정의
3. procedural/example/trade-off lint 범주 검토
4. JSON Schema enum 업데이트
5. intent가 unique하고 최소 section 수를 만족하는 테스트 추가
새 유형을 만들기 전에 기존 유형의 하위 section으로 충분한지 확인한다. 유형이 늘수록 분류 실패 비용도 커진다.
## 새 source type 추가
## 새로운 lint rule
1. `corpus._classify_source`에 path rule 추가
2. `_SOURCE_WEIGHTS`에 기본 weight 추가
3. prompt의 source hierarchy에 claim role 정의
4. canonical/current state와 rationale/history 충돌 규칙 작성
5. ranking과 provenance 테스트 추가
좋은 결정적 rule은 다음 조건을 만족한다.
## 새 reviewer 추가
- 모델 없이 같은 입력에 같은 결과
- 결함 위치와 수정 방향을 설명
- false positive가 관리 가능
- blocker/error/warning/info의 위험 수준이 명확
- 자연어 의미 전체를 안다고 가장하지 않음
Pipeline config의 reviewer role은 자유 문자열이지만 중복될 수 없다. role-specific prompt가 필요하면 `ROLE_GUIDANCE`에 추가한다.
`LintIssue`의 code prefix를 기존 범주에 맞춘다.
추천 role:
- `MD`: Markdown 무결성
- `STR`: 구조
- `AUD`: 독자/오프닝
- `READ`: 가독성 proxy
- `TYPE`: 문서 유형 계약
- `EVD`: 근거
- `SAFE`: 안전
- `VER`: 버전
- `LEN`: 길이
- `FIN`: 미완료 표시
- `editor`: 문장과 heading
- `security`: threat model과 secret exposure
- `api`: contract compatibility
- `domain-owner`: project-specific correctness
## 새로운 reviewer role
Model review response는 모든 `REVIEW_DIMENSIONS`를 포함해야 한다.
1. `prompts.py``ROLE_GUIDANCE`에 실패 함수를 정의한다.
2. pipeline config reviewers에 role/provider를 추가한다.
3. 공통 9개 dimension을 유지하거나 조직용 dimension을 parser와 보고서에 명시적으로 확장한다.
4. 다른 reviewer와 중복되는 일반 교정이 아니라 독립적인 결함 탐지 관점을 제공한다.
## 새 provider 추가
예: accessibility, localization, API consistency, security threat modeling.
`Provider` interface를 구현한다.
## 출처 자동 수집기
```python
class MyProvider(Provider):
def generate(self, request: ProviderRequest) -> ProviderResponse:
...
Core pipeline은 URL을 자동 방문하지 않는다. 수집기를 추가할 때는 별도 단계로 분리한다.
```text
retriever → immutable evidence snapshot → fact extractor → human/source-owner approval → SourcePack
def check(self) -> dict[str, object]:
...
```
최종 source pack에는 원문 snapshot hash, 추출 위치, 접근 날짜, 허용된 fact를 남기는 것이 바람직하다. 검색 결과 요약을 바로 source truth로 쓰지 않는다.
요구사항:
## 실행 가능한 코드 검증
- prompt는 stdin 또는 안전한 API body로 전달
- timeout 강제
- command/error를 audit event로 남길 수 있음
- cwd 복원과 output isolation
- credential을 response/event에 기록하지 않음
- fake executable 또는 fake SDK unit test
코드 블록을 테스트하려면 document generation과 별도의 verifier를 둔다.
## Rationale lint 확장
1. 언어 태그와 fixture를 추출한다.
2. 격리된 container/sandbox에서 실행한다.
3. expected output과 비교한다.
4. 결과와 로그를 evidence artifact로 저장한다.
5. 문서의 예시 section과 artifact hash를 연결한다.
현재 `RAT001``RAT002`는 lexical heuristic이다. 특정 조직의 decision record가 structured field를 갖고 있다면 다음 확장이 가능하다.
문서 모델에게 “코드가 맞다”고 평가하게 하는 것만으로 실행 검증을 대체하지 않는다.
- decision ID별 required claim type
- alternative/accepted-cost/guardrail field validation
- source heading과 claim ID 기반 completeness score
- canonical implementation state와 branch rationale join
Score를 높이기 위해 heuristic을 약화하지 않는다. false positive를 줄일 때는 regression fixture와 golden example을 함께 추가한다.
+91 -134
View File
@@ -1,168 +1,125 @@
# Logic model for comprehensible technical documents
# Logic model
## 1. 문서는 질문 그래프다
## 1. 독자 질문의 순서
좋은 기술 문서를 “서론-본론-결론”이라는 형식만으로 설명하면 부족하다. 실제 독자는 순차적으로 다음 질문을 해결한다.
좋은 기술 글은 정보량보다 질문의 순서를 통제한다. 기술 블로그의 기본 질문은 다음과 같다.
```text
왜 읽어야 하는가?
정확히 무엇을 다루는가?
무엇을 이미 알아야 하는가?
핵심 답 또는 결과는 무엇인가?
그 답이 성립하는 이유와 메커니즘은 무엇인가?
구체적인 사례에서 어떻게 보이는가?
어떻게 확인하는가?
언제 실패하거나 선택하지 않아야 하는가?
그래서 무엇을 해야 하는가?
무슨 문제가 있었나?
왜 단순히 풀 수 없었나?
무엇을 검토했나?
왜 이 선택을 했나?
코드에서는 어떻게 동작하나?
무엇으로 확인했나?
어떤 비용과 한계가 남았나?
내 환경에서 무엇을 판단해야 하나?
```
모든 문서가 이 질문을 동일한 비중으로 다루지는 않는다. 문서 유형은 **독자의 현재 상태와 목적**에 따라 필요한 질문 부분을 선택하고 순서를 최적화한 것이다.
제목은 이 질문에 대한 표지판이어야 한다. `개요`, `상세`, `기타`처럼 정보 역할을 드러내지 않는 heading은 경고 대상이다.
## 2. 문서 유형을 섞을 때의 규칙
## 2. Decision unit
한 페이지에 여러 유형이 존재할 수 있지만 주된 목적은 하나여야 한다.
기술 선택은 다음 6요소를 하나의 논리 단위로 본다.
- Tutorial 안의 짧은 explanation은 현재 단계를 이해시키는 데 필요한 만큼만 둔다.
- How-to 안의 reference table은 절차 수행에 필요한 조회 표면으로 제한한다.
- Technical blog 안의 code example은 전체 API reference가 아니라 인과 관계를 보여준다.
- Reference 안의 장황한 배경 설명은 별도 explanation으로 분리한다.
- Troubleshooting 안의 fix는 확인된 cause branch에만 연결한다.
| 요소 | 질문 |
|---|---|
| context/constraint | 어떤 문제와 제약 아래에서 결정했는가 |
| choice | 무엇을 선택·허용·금지했는가 |
| why | 그 선택이 어떤 비용이나 위험을 줄였는가 |
| alternative | 현실적인 다른 선택은 무엇이었는가 |
| accepted cost | 선택 때문에 무엇을 감수했는가 |
| guardrail | 허용 범위가 넓어지지 않게 무엇이 실패하는가 |
판정 질문:
“X를 의도적으로 사용한다”는 choice 하나만 있다. 이유가 없으면 `RAT001`, 대안·비용·가드레일이 없으면 `RAT002` 후보가 된다.
> 이 부분이 독자의 현재 목표를 직접 전진시키는가, 아니면 다른 문서 유형의 목표를 새로 시작하는가?
## 3. Evidence semantics
후자라면 분리하거나 링크한다.
근거는 단어 일치가 아니라 claim role로 배치한다.
## 3. 논리 구조의 최소 단위
- **current state**: canonical project가 우선
- **decision history and rationale**: branch note가 유용
- **vendor/protocol behavior**: official docs
- **precedent**: company tech blog
- **general explanation**: canonical concept 또는 안정적인 background knowledge
### Section contract
공식 문서가 `@Service`의 동작을 설명해도 프로젝트가 왜 그것을 선택했는지는 증명하지 않는다. 반대로 branch note가 선택 이유를 설명해도 현재 구현 상태가 바뀌었다면 canonical source를 확인해야 한다.
각 section은 다음을 가진다.
## 4. Status boundary
1. **Reader question**: 독자가 이 시점에 묻는 질문
2. **Purpose**: 이 절이 수행할 정보 작업
3. **Claim/answer**: 질문에 대한 명시적 답
4. **Support**: 근거, 메커니즘, 예시 또는 절차
5. **Boundary**: 답이 유효한 범위와 예외
6. **Transition**: 다음 질문이 왜 생기는지 연결
### Paragraph contract
문단은 보통 다음 순서를 사용한다.
다음 status를 서로 바꾸어 쓰지 않는다.
```text
중심 문장 → 이유/근거 → 구체화/예시 → 다음 문장으로의 연결
actually implemented
locally verified
production verified
documented only
planned
needs confirmation
unsupported
```
문단이 두 개의 독립 결론을 갖거나, 첫 문장이 뒤의 내용을 예고하지 못하거나, 마지막 문장이 새 주제를 시작하면 분리 후보로 본다.
로컬 ArchUnit test 통과는 운영 효과의 증거가 아니다. 다른 회사의 사례는 이 프로젝트가 같은 결과를 얻었다는 증거가 아니다.
## 4. 이해를 돕는 인과 구조
## 5. Concrete example
기술 설명에서 목록만 나열하면 독자는 구성요소를 기억해도 시스템을 예측하지 못한다. 메커니즘 section은 다음 중 하나의 명시적 순서를 사용한다.
- 시간: 요청 전 → 요청 중 → 응답 후
- 데이터 흐름: 입력 → 변환 → 저장 → 출력
- 제어 흐름: 조건 → 분기 → 행동 → 상태 전이
- 장애 흐름: 트리거 → 증상 → 전파 → 완화 → 복구
- 결정 흐름: 제약 → 비교 기준 → 대안 평가 → 선택 → 수용 비용
각 화살표에는 “왜 다음 상태가 되는가”가 있어야 한다. 단순히 컴포넌트 이름을 이어 붙이지 않는다.
## 5. 점진 공개
독자가 세부사항을 이해하기 위한 구조를 먼저 제공한다.
1. 핵심 답/결과
2. 범위와 전제
3. 가장 단순한 모델
4. 정상 메커니즘
5. 완주하는 예시
6. 검증
7. 예외·실패·트레이드오프
8. 운영 세부사항
예외를 너무 일찍 넣으면 기본 모델을 형성하기 어렵고, 너무 늦게 숨기면 과도한 확신을 준다. 기본 모델을 제시한 직후 “어디까지 유효한가”를 명시하고, 상세 예외는 뒤에서 확장한다.
## 6. Worked example 계약
예시는 코드 조각의 존재가 아니라 **시작 상태부터 검증 결과까지의 연결**이다.
필수 요소:
- 초기 상태와 입력
- 각 단계의 행동 또는 상태 변화
- 단계의 이유
- 예상 관측
- 최종 결과
- 성공 기준
- 실패했을 때 되돌아갈 지점
초보 독자에게는 중간 추론을 더 많이 보이고, 숙련 독자용 문서에서는 자명한 단계를 줄인다. 브리프의 `prior_knowledge`가 이 깊이를 결정한다.
## 7. 근거와 주장 수준
문장은 다음 네 종류 중 하나로 분류할 수 있어야 한다.
| 종류 | 예 | 처리 |
|---|---|---|
| 관측 사실 | 특정 로그가 발생했다 | 출처·실험·측정 연결 |
| 일반 기술 사실 | 프로토콜 의미, API 계약 | 권위 있는 reference 연결 |
| 가정/가상 예시 | 설명을 위한 단순 모델 | 가정/예시임을 표시 |
| 권고/판단 | 이 조건에서는 A를 선택 | 기준·대안·비용을 공개 |
“관련된 출처”와 “그 주장을 지지하는 출처”는 다르다. Source pack의 `facts`는 허용된 주장 범위를 줄이는 역할을 한다.
## 8. 트레이드오프 구조
좋은 기술 글은 선택을 미화하지 않는다.
예시는 최종 코드 조각만 보여주지 않는다.
```text
선택한 접근
├── 얻는 것
├── 지불하는 비용
├── 대안
├── 선택 기준
├── 실패 조건
└── 선택하지 말아야 하는 상황
initial state
→ input
→ decision criterion
→ selected path
→ state/control-flow change
→ observable result
→ success or recovery criterion
```
대안을 비교할 때는 같은 기준을 사용한다. 한 대안은 성능으로, 다른 대안은 구현 편의성으로만 설명하면 비교가 성립하지 않는다.
독자는 예시에서 추상 모델의 각 요소를 대응시킬 수 있어야 한다.
## 9. 절차 안전성
## 6. Korean problem-solving blog profile
절차 문서의 단계는 다음 상태 머신으로 본다.
`woowahan_tech_blog_ko` profile은 다음을 권장한다.
```text
PRECONDITION_CHECKED
→ CHECKPOINT_CREATED
→ CHANGE_APPLIED
→ EXPECTED_RESULT_OBSERVED
→ VERIFIED
```
- 팀이나 시스템의 구체적 맥락에서 시작
- 기술 이름보다 문제와 비용을 먼저 설명
- 기존 방식, 실패한 시도, 대안을 숨기지 않음
- 선택 기준과 이유를 명시
- 구현 세부가 앞에서 세운 문제에 답하도록 구성
- 검증 결과를 원래 문제에 다시 연결
- project-local 결정을 보편 규칙으로 쓰지 않음
- 억지 접속어보다 문단 사이의 실제 논리 관계를 수정
- `문제 → 제약 → 대안 → 선택`을 의미 순서로 사용하되 문장 틀로 읽어 주지 않음
- 문단을 행위자, 상태, 변화, 결과, 판단에서 시작
- 질문형 heading은 바로 다음 문장에서 답하고, 접속어는 실제 인과·역접을 가리키게 함
- 순서어는 실제 단계·방법·레이어·도표에 사용하고, 추상 분류는 목록이나 의미 있는 소제목으로 표현
어느 단계에서든 불일치하면 다음으로 진행하지 않고 `STOPPED → ROLLED_BACK → RECOVERY_VERIFIED`로 이동해야 한다. 파괴적 명령은 경고 문구만으로 충분하지 않으며 백업/복구점, 영향 범위, 확인 명령이 함께 있어야 한다.
이는 샘플 글에서 관찰한 패턴을 하네스 규칙으로 번역한 것이며 공식 house style은 아니다.
## 10. 품질 평가 차원
특히 `첫 번째 제약은`, `두 번째 제약은`, `세 번째 제약은`처럼 outline의 분류명을 연속 문단 머리에 두는 방식은 정보 구조를 산문으로 노출한다. 한국어 기술 블로그에서 이런 형식이 가까운 문단에 세 번 이상 나타나면 `STYLE001` warning 대상이다. 실제 순서를 설명하는 번호 목록과 단계 문장은 대상이 아니다.
모델 reviewer는 다음 차원을 각각 검사한다.
## 7. Date and citation logic
- `reader_goal_alignment`: 약속한 결과를 실제로 제공하는가
- `information_architecture`: 문서 유형과 section 역할이 맞는가
- `logical_flow`: 전제·인과·결론·전환이 끊기지 않는가
- `cognitive_load`: 선행지식에 맞고 세부사항이 점진적으로 공개되는가
- `evidence_traceability`: 확인 가능한 주장이 근거와 연결되는가
- `example_verifiability`: 예시가 끝까지 실행·검증 가능한가
- `scannability`: heading과 첫 문장만 읽어도 구조가 보이는가
- `operational_safety`: 절차·변경·실패·복구가 안전한가
- `completeness_and_limits`: 범위, 비범위, 예외, 트레이드오프가 있는가
- access date는 provenance
- version/date가 behavior, compatibility, reproducibility를 바꿀 때만 본문에 사용
- hidden citation mode에서는 internal marker 금지
- public citation이 필요하면 footnote 또는 inline link 사용
한 차원의 평균이 전체 결함을 숨기지 않도록 blocker/error 개수를 점수와 별도로 게이트한다.
## 8. Lint와 model review의 역할 분리
Deterministic lint가 잘하는 것:
- heading 계약
- source marker/path/date/meta 문자열 누출
- 명시적 choice 뒤 rationale 어휘 부재
- 반복된 서수 문단처럼 형식적으로 식별 가능한 문장 scaffolding
- 절차 구조와 파괴적 command safety
Model review가 필요한 것:
- 이유가 실제로 선택을 정당화하는가
- 대안 비교가 공정한가
- source chunk가 claim을 충분히 지지하는가
- 문단 흐름과 독자 인지 부하
- 질문이 바로 답을 얻고 접속어가 실제 관계를 가리키는가
- 정보 구조가 기계적인 문장 틀로 노출됐는가
- project-local policy의 과장 여부
+27 -124
View File
@@ -1,155 +1,58 @@
# Provider integration
## 공통 계약
모든 provider는 다음 인터페이스를 구현한다.
```python
Provider.generate(ProviderRequest) -> ProviderResponse
Provider.check() -> dict
```
`ProviderRequest``stage`, `prompt`, `workdir`, `metadata`를 가진다. `ProviderResponse`는 모델의 텍스트, provider/model 이름, 실제 command 또는 실행 메타데이터를 반환한다.
Provider는 초안의 의미를 해석하지 않는다. 호출·timeout·출력 수집만 담당하며 JSON/Markdown 계약 검증은 pipeline에서 수행한다.
# Provider integrations
## Codex
기본 command 개념:
기본 command:
```text
codex exec
--sandbox read-only
--skip-git-repo-check
[--model MODEL]
--output-last-message TEMP_FILE
-
codex exec --sandbox read-only --output-last-message <file> -
```
프롬프트는 stdin으로 전달한다. `-`는 비대화형 입력을 의미하고, 마지막 메시지는 임시 파일에서 읽는다. 문서 생성은 로컬 파일 변경이 필요 없으므로 기본 sandbox를 read-only로 둔다.
Prompt는 stdin으로 전달한다. planner, logic reviewer, decision reviewer에 사용한다. `skip_git_repo_check``extra_args`는 provider option으로 설정할 수 있다.
설정 예:
## Claude
```json
{
"provider": "codex",
"model": "",
"timeout_seconds": 300,
"options": {
"binary": "codex",
"sandbox": "read-only",
"skip_git_repo_check": true,
"extra_args": []
}
}
```
환경 변수 `CLARIDOC_CODEX_BIN`으로 실행 파일을 지정할 수도 있다.
조직 래퍼:
```json
{
"provider": "codex",
"options": {
"command": ["/trusted/path/company-codex-wrapper", "--batch"]
}
}
```
custom command는 stdout을 최종 응답으로 사용한다.
## Claude Code
기본 command 개념:
기본 command:
```text
claude -p --output-format text [--model MODEL] "Read the piped task..."
claude -p --output-format text
```
긴 프롬프트는 운영체제 argument 길이 제한을 피하기 위해 stdin으로 전달한다. 마지막 고정 query는 piped task의 출력 계약만 수행하도록 지시한다.
설정 예:
```json
{
"provider": "claude",
"model": "",
"timeout_seconds": 600,
"options": {
"binary": "claude",
"extra_args": []
}
}
```
환경 변수 `CLARIDOC_CLAUDE_BIN` 또는 신뢰된 `options.command`를 사용할 수 있다.
Prompt는 stdin으로 전달한다. primary writer, reader reviewer, editor reviewer, reviser에 사용한다.
## Google Antigravity
Antigravity는 Python SDK를 사용한다.
Python SDK 표면:
```python
from google.antigravity import Agent, LocalAgentConfig
config = LocalAgentConfig(**options["config"])
async with Agent(config) as agent:
response = await agent.chat(prompt)
text = await response.text()
```
설치:
`LocalAgentConfig`로 model과 config를 전달하고 async `chat` 결과의 text를 읽는다. evidence와 operations reviewer에 사용한다.
## Model IDs
예제 config는 model ID를 비워 provider 계정의 기본 선택을 사용한다. 조직에서 허용된 model ID가 있다면 각 provider object의 `model`에 지정한다. 모델 이름과 availability는 계정·시점마다 달라질 수 있으므로 `doctor`와 live smoke test로 확인한다.
## Doctor
```bash
python -m pip install -e '.[antigravity]'
claridoc doctor --config config/pipeline.multi-agent.example.json
```
설정 예:
`doctor`가 확인하는 것:
```json
{
"provider": "antigravity",
"model": "",
"timeout_seconds": 300,
"options": {
"config": {}
}
}
```
- CLI executable 또는 SDK import 가능 여부
- 설정된 integration surface
`model`이 지정되고 `options.config`에 model이 없으면 하네스가 config 인수로 전달한다. SDK 버전에 따라 지원 인수가 다를 수 있으므로 잘못된 config는 명시적 오류로 종료한다.
확인하지 않는 것:
SDK가 로컬 환경을 기준으로 동작하므로 provider는 실행 중 임시로 run directory를 current working directory로 사용한다. 프로세스 전체 cwd가 공유 상태이므로 lock으로 직렬화한다.
- 로그인 유효성
- project/repository 접근 권한
- quota와 rate limit
- model ID availability
- 실제 response schema 안정성
## Mock
Mock은 외부 모델이 아니다. 다음을 위한 결정적 fixture다.
- planner JSON 계약 검증
- writer Markdown 배선 검증
- review JSON 파싱 검증
- revision loop 및 산출물 테스트
- CI에서 네트워크·인증 없이 회귀 테스트
Mock 점수는 실제 품질 판단으로 사용하면 안 된다.
## `doctor`
```bash
claridoc doctor --config config/pipeline.multi-agent.example.json --json
```
- Codex/Claude: 실행 파일 경로 존재 확인
- Antigravity: Python module import 가능 여부 확인
- Mock: 항상 available
`doctor`는 로그인·권한·quota·실제 모델 응답까지 확인하지 않는다. 그것은 live invocation에서만 확인된다.
## Provider 추가
1. `src/claridoc/providers/``Provider` 구현을 추가한다.
2. stdout/SDK 응답을 문자열로 반환하고 timeout과 오류를 `ProviderError` 계열로 변환한다.
3. `registry.py`에 이름을 등록한다.
4. command/SDK를 가짜 구현으로 대체한 단위 테스트를 작성한다.
5. 인증 비밀은 config나 event log에 넣지 않는다.
6. 모델 출력 계약은 provider가 아니라 `prompts.py`와 pipeline parser에서 유지한다.
Mock provider는 deterministic fixture다. source excerpt를 최종 글에 복사하지 않으며, 외부 model을 호출하지 않는다. Mock reviewer score는 합성값이다.
+46 -87
View File
@@ -1,110 +1,69 @@
# Security and trust model
# Security and trust boundaries
## 보호 대상
## 1. 주요 자산
- provider 인증 정보와 로컬 계정
- 실행 호스트의 파일·명령·네트워크 권한
- 비공개 brief, source pack, draft
- 출처 진실성과 최종 문서 정확성
- 품질 게이트의 무결성
- provider credential과 local authentication state
- private repository의 source text와 경로
- draft와 내부 decision record
- provider raw response와 event log
- 최종 독자용 문서
## 위협과 완화
## 2. Prompt injection 경계
### 1. Source/brief prompt injection
Brief, source chunk, title, URL, note, draft는 모두 untrusted data다. 모든 stage prompt는 source 내부 지시를 따르지 말고 내용으로만 취급하도록 명시한다.
위협: title, fact, note, URL, draft 안에 “이전 지시를 무시하라” 같은 문장이 들어간다.
완전한 prompt-injection 제거를 보장하지 않는다. 민감한 저장소에서는 다음을 권장한다.
완화:
- provider가 읽어도 되는 corpus root만 지정
- `--source-include`로 최소 directory만 허용
- secret, credential, production dump를 corpus에 포함하지 않음
- provider CLI의 sandbox와 조직 정책 사용
- 최종 provenance artifact의 접근 권한 제한
- 모든 prompt에서 입력 블록을 명시적으로 untrusted data로 선언
- 출력 스키마와 stage 역할을 입력 블록 밖에 정의
- planner의 구조 변경을 코드로 검증
- reviewer 결과도 JSON 파싱과 severity 계약으로 제한
- 최종 출력에 결정적 린트와 독립 리뷰 적용
## 3. Reader-facing data minimization
잔여 위험: 언어 모델이 경계를 무시할 수 있다. 고위험 입력은 별도 sanitization, 제공자 정책, 인간 검토가 필요하다.
`citation_style=hidden`의 목적은 내부 근거를 없애는 것이 아니라 노출 표면을 줄이는 것이다.
### 2. Command injection
독자용 문서에서 금지:
위협: provider command가 외부 입력으로 조작된다.
- source ID와 claim/decision ID
- absolute/local repository path
- access date
- frontmatter와 status field
- prompt tag
- evidence-processing narration
완화:
내부 audit artifact에는 이 metadata가 남으므로, run directory 자체는 private data로 취급해야 한다.
- subprocess는 shell 없이 argument list로 실행
- brief/source 값을 command에 삽입하지 않고 stdin으로 전달
- `options.command`는 로컬 운영자가 승인한 config만 허용한다고 문서화
- 인증 비밀을 command line에 넣지 않음
## 4. Command execution
잔여 위험: 악의적인 pipeline config 자체는 임의의 로컬 executable을 실행할 수 있다. config를 코드와 같은 신뢰 수준으로 관리해야 한다.
- Codex 기본 설정은 read-only sandbox다.
- writer/reviewer prompt는 shell 실행이나 file mutation을 요구하지 않는다.
- `options.command`, provider binary path, extra args는 신뢰된 local config로만 설정한다.
- 사용자 또는 source text에서 command option을 동적으로 만들지 않는다.
### 3. 모델의 파일/명령 부작용
## 5. Destructive content
위협: 에이전트 도구가 파일을 수정하거나 command를 실행한다.
문서 안에 `rm -rf`, `DROP DATABASE`, `kubectl delete`, `terraform destroy` 등 파괴적 command가 있으면 주변에 다음이 모두 필요하다.
완화:
- 영향 경고
- backup/checkpoint/recovery
- expected effect
- read-only verification
- Codex 기본 sandbox `read-only`
- 작성 prompt는 파일 수정이나 shell 사용을 요구하지 않음
- Claude는 print mode 텍스트 출력을 사용
- Antigravity에는 문서 생성 prompt만 전달
이 검사는 command가 실제 환경에서 안전하다는 보증이 아니다.
잔여 위험: provider 자체 설정이나 조직 wrapper가 더 넓은 권한을 부여할 수 있다. 최소 권한과 격리 환경을 별도로 적용한다.
## 6. Provenance integrity
### 4. 근거 세탁과 허위 인용
`manifest.json`은 run artifact의 byte size와 SHA-256을 기록한다. manifest 생성 이후 파일이 바뀌면 재검산에서 드러난다. 전자서명이나 원격 attestation은 제공하지 않는다.
위협: 모델이 관련만 있는 출처를 주장 근거처럼 붙이거나 source ID를 지어낸다.
## 7. Provider credentials
완화:
Credential을 repository, brief, source pack, event log에 저장하지 않는다. Codex/Claude CLI와 Antigravity SDK의 표준 인증 방식을 사용한다. `doctor`는 설치 가능성만 확인하며 로그인, 권한, quota를 증명하지 않는다.
- source pack에 출처가 지지하는 `facts`를 명시
- 존재하지 않는 source ID를 error로 처리
- evidence reviewer가 claim-marker fit를 검사
- 원문 model response와 source pack을 보존
## 8. Known limits
잔여 위험: 하네스는 URL의 실제 내용이 `facts`와 일치하는지 자동 검증하지 않는다. source pack 작성자의 검증이 필요하다.
### 5. 위험한 절차
위협: 문서가 `rm -rf`, `DROP TABLE`, `kubectl delete`, `terraform destroy` 같은 명령을 안전장치 없이 제공한다.
완화:
- 대표 파괴 패턴을 blocker로 검사
- 주변에 경고, 백업/복구, 롤백 문맥 요구
- operations reviewer로 절차 상태 전이 검사
잔여 위험: 패턴 목록은 완전하지 않으며 도메인별 위험 명령을 모두 알 수 없다. 조직별 lint rule 확장이 필요하다.
### 6. 점수 조작
위협: 모델 reviewer가 근거 없이 높은 점수를 주거나 초안 내부 지시를 따른다.
완화:
- 결정적 lint 점수와 모델 평균을 혼합
- blocker/error 개수를 별도 gate
- 여러 provider와 역할을 분리 가능
- raw review를 보존
잔여 위험: 여러 reviewer가 같은 모델 계열·학습 편향을 공유할 수 있다. 고위험 문서는 인간 reviewer와 실행 가능한 검증을 추가한다.
### 7. 민감 정보 유출
위협: brief/source/draft가 외부 모델 제공자에 전송된다.
완화:
- 하네스가 실제로 전송하는 prompt를 raw artifact로 확인 가능
- provider별 조직 정책과 계정을 사용
- Mock으로 로컬 배선 테스트 가능
잔여 위험: live provider를 사용하면 해당 제공자의 처리 경계로 데이터가 이동한다. 비밀·개인정보·규제 데이터를 넣기 전에 조직 정책을 확인하고 필요한 경우 로컬 모델 adapter를 추가한다.
## 운영 권고
- pipeline config는 코드 리뷰와 버전 관리를 적용한다.
- provider model ID와 CLI/SDK 버전을 배포 메타데이터에 고정한다.
- run directory 접근 권한과 보존 기간을 정의한다.
- 고위험 문서는 source pack 작성자와 최종 승인자를 분리한다.
- 실제 명령과 코드는 sandbox/CI에서 실행해 결과를 source pack 또는 별도 evidence artifact로 연결한다.
- PASS 문서를 자동 게시하지 말고, 위험도에 맞는 승인 단계를 둔다.
- lexical retrieval이 민감한 문서를 선택할 수 있으므로 corpus scope를 운영자가 통제해야 한다.
- model이 source text를 재구성하면서 민감 정보를 노출할 수 있다.
- hidden citation lint는 알려진 path와 marker pattern을 검사하지만 모든 비밀 문자열을 탐지하지 않는다.
- private source에서 공개 가능한 결론을 만드는 책임은 프로젝트 소유자에게 있다.