# ClariDoc Harness 0.2.0 검증 보고서 - 검증 대상: `claridoc-harness 0.2.0` - 검증 환경: Linux, Python 3.12.3 runtime - 하위 문법 호환 검사: Python 3.10 AST grammar - 검증 명령: 변경 중인 working tree 산출물을 덮어쓰지 않도록 격리된 working-copy에서 `bash scripts/verify.sh` ## 1. 이번 수정에서 검증하려는 실패 0.2.0은 단순한 기능 추가가 아니라 다음 회귀를 차단하는 수정이다. 1. 독자용 글에 source ID, 저장소 경로, 접근일, prompt 문장이 나타나는 문제 2. “의도적으로 사용한다”는 선택 선언 뒤에 이유·대안·비용이 없는 문제 3. 프로젝트의 branch-note와 canonical 문서를 검색하지 않고 일반론으로 이유를 채우는 문제 4. 근거에서 이유를 확인하지 못한 SLF4J 선택을 그럴듯하게 설명하는 문제 5. 독자용 문서와 내부 provenance가 같은 파일에 섞이는 문제 6. `문제 → 제약 → 대안 → 선택 이유`라는 정보 구조가 `첫 번째 제약은` 같은 반복 문장 틀로 노출되는 문제 검증 스크립트는 이 실패를 unit test와 별도의 artifact-level 회귀 검사로 모두 확인한다. ## 2. 전체 결과 | 검증 항목 | 결과 | |---|---:| | 단위·통합 테스트 | **44/44 PASS** | | Statement coverage | **미수집 — coverage package 없음** | | Python 3.10 grammar parse | **31개 파일 PASS** | | JSON 구문 검사 | **35개 파일 PASS** | | Draft 2020-12 schema 자체 검사 | **5개 schema PASS** | | 대표 JSON instance schema 검증 | **5개 instance PASS** | | Markdown local link | **187개 PASS** | | Local corpus 검색 | **10개 evidence chunk 회수** | | Decision-rationale ranking | **D13 이유 chunk 1위** | | Golden example lint | **100.0/100, blocker 0, error 0** | | Golden reader-facing leakage 검사 | **PASS** | | Unsupported SLF4J rationale 검사 | **PASS** | | Mock 종단 간 pipeline | **PASS, 95.6/100** | | Reader/provenance artifact 분리 | **PASS** | | Manifest size·SHA-256 재검산 | **PASS** | | Wheel 빌드 | **PASS** | | 새 virtualenv wheel 설치 | **PASS** | | 설치된 CLI validate/collect/lint/run | **PASS** | | 실제 Codex·Claude·Antigravity 호출 | **미수행 — Codex·Claude CLI 확인, Antigravity SDK 없음** | ## 3. 테스트와 coverage 실행: ```bash PYTHONPATH=src python3 -m unittest discover -s tests -v ``` 결과: ```text Ran 44 tests OK coverage package unavailable; coverage report skipped ``` 주요 신규 회귀 테스트: - local corpus에서 Spring DI 선택 이유가 있는 D13 chunk가 우선 검색되는지 - repository-relative path와 line range가 보존되는지 - canonical current-state와 branch decision-history가 함께 회수되는지 - 독자용 글의 source marker와 meta narration을 error로 잡는지 - access-date boilerplate를 잡는지 - 선택 선언 뒤 이유가 없으면 `RAT001`로 실패하는지 - golden application-core 예시가 blocker/error 없이 통과하는지 - heading만 있고 본문이 없는 chunk를 evidence로 수집하지 않는지 - final artifact에 `provenance.md`와 `evidence-map.json`이 생성되는지 - 한국어 기술 블로그에서 추상 분류명을 세 개의 서수 문단 머리로 반복하면 `STYLE001`이 발생하는지 - 실제 절차를 나타내는 번호 목록은 `STYLE001`로 오인하지 않는지 - writer·editor·reviser prompt가 정보 구조와 문장 형식을 구분하고 실제 순서 표현은 보존하는지 이번 환경에는 `coverage` package가 없어 statement coverage를 다시 계산하지 않았다. Coverage 수치가 있더라도 사실 정확성이나 provider 품질을 증명하지는 않는다. ## 4. Local corpus와 결정 근거 회수 fixture corpus는 실제 저장소 구조를 축소해 다음 경로를 포함한다. ```text wiki/projects/ca-tmpl raw/branch-notes raw/official-docs raw/company-tech-blogs ``` 검색 질의: ```text application-core Spring DI 선택 이유 대안 비용 가드레일 TransactionPort spring-tx 금지 ArchUnit 검증 ``` 회수 결과는 10개 heading chunk였으며, 1위는 다음 내용을 포함한 branch-note의 `결정 사항`이었다. ```text D13: @Service/@Component를 DI 등록 목적으로 허용 이유: DI까지 제거하면 use case bean 수동 @Configuration 등록이 증가 수용 비용: spring-context/spring-beans 의존 경계: spring-tx, Spring Web, JPA 금지 ``` 동시에 canonical project 문서에서 Gradle/ArchUnit 검사와 reflection-style bypass 한계를 회수했다. 수집 JSON에는 절대 경로가 없고 repository-relative path와 line range만 남았다. Negative evidence fixture에는 “이 문서는 application-core가 SLF4J를 사용하는 이유를 설명하지 않는다”는 경계를 넣었다. golden reader-facing example에서 `SLF4J`가 발견되면 검증이 실패하도록 했다. ## 5. Golden reader-facing example 대상: ```text examples/golden/application-core-spring-di-boundary.md ``` Lint 결과: ```text score: 100.0 word_count: 993 issues: 0 H1: 1 H2: 8 citation_style: hidden has_verification: true has_tradeoffs: true formulaic_ordinal_opening_count: 0 ``` 별도 leakage 검사에서 다음 패턴이 없어야 통과한다. ```text [S1] 또는 [L...] 내부 marker 근거 팩 / 확인 대상으로 제시 예시는 YYYY-MM-DD 기준 raw/branch-notes/ 또는 wiki/projects/ 경로 repo:/// URL /home/... 절대 경로 ``` Golden 글에는 Spring DI 허용 이유, 엄격한 무-Spring 대안, 광범위한 Spring 허용 대안, 수용 비용, TransactionPort, Gradle/ArchUnit 가드레일, 정적 분석의 한계가 포함된다. 명시적 이유를 확보하지 못한 SLF4J는 제외했다. ## 6. Mock 종단 간 pipeline 실행: ```bash bash scripts/run-demo.sh ``` 결과: ```text GATE: PASS SCORE: 95.6/100 ``` 세부 결과: ```text deterministic lint: 95.0 logic review: 96.0 decision review: 96.0 reader review: 96.0 editor review: 96.0 evidence review: 96.0 operations review: 96.0 blockers: 0 errors: 0 ``` 이 점수는 deterministic mock fixture의 합성값이다. `run.json`에 다음 경고가 자동 기록된다. ```text All providers are deterministic mocks. This run validates pipeline mechanics only; model-review scores are synthetic and must not be used as evidence of document quality. ``` 따라서 95.6점은 planner/writer와 logic·decision·reader·editor·evidence·operations reviewer, reviser 배선, 계약 파싱, lint, gate, artifact 생성이 동작했다는 의미다. 실제 모델의 문장 품질을 뜻하지 않는다. ## 7. Reader-facing 문서와 provenance 분리 Mock pipeline은 다음을 별도 생성했다. ```text final/document.md final/quality-report.md final/provenance.md final/evidence-map.json ``` 검사 결과: - `document.md`에는 내부 source marker, repository path, access-date boilerplate가 없음 - `provenance.md`와 `evidence-map.json`에는 source ID와 감사 정보가 보존됨 - `run.json`이 네 artifact의 역할을 각각 기록함 - `manifest.json`이 네 artifact를 모두 포함함 - manifest의 byte size와 SHA-256을 실제 파일에서 다시 계산해 일치함 ## 8. 정적·schema·링크 검사 ```text 31 Python files: Python 3.10 grammar parse PASS 35 JSON files: parse PASS 5 schemas: Draft 2020-12 check_schema PASS 5 representative instances: validation PASS 187 relative Markdown links: target exists ``` 대표 schema instance: - retry-policy brief - application-core brief - manual retry source pack - local corpus source pack - generated application-core outline ## 9. Wheel 빌드와 깨끗한 설치 격리된 검증 복사본의 산출물: ```text dist/claridoc_harness-0.2.0-py3-none-any.whl size: 76325 bytes SHA-256: 5f873d5261273e2b0165d4ad0e6e938b4ee98fe1aaa09cb60e13d7f61bf535e6 ``` 검증 절차: 1. PEP 517 wheel 빌드 2. 임시 virtualenv 생성 3. wheel을 `--force-reinstall --no-deps`로 설치 4. 설치된 `claridoc --version` 실행 5. 설치된 CLI로 local-corpus `validate` 6. 설치된 CLI로 `collect` 7. 설치된 CLI로 golden `lint` 8. 설치된 CLI로 Mock pipeline `run` 결과: ```text claridoc 0.2.0 validate: PASS, 10 sources collect: PASS, 8 evidence chunks lint: PASS mock run: PASS, 95.6/100 ``` ## 10. Provider 검증 수준 | Provider | 구현 표면 | 자동 테스트 | 현재 live 호출 | |---|---|---|---| | Codex | `codex exec`, stdin, `--output-last-message`, read-only sandbox | fake executable로 command와 결과 수집 검증 | 미수행 | | Claude | `claude -p --output-format text`, stdin | fake executable로 piped prompt와 stdout 검증 | 미수행 | | Antigravity | SDK `Agent`, `LocalAgentConfig`, async `chat` | fake SDK로 model/config/cwd/async 응답 검증 | 미수행 | `doctor` 결과: ```text [OK] codex: codex exec [OK] claude: claude -p [MISSING] antigravity: google-antigravity SDK ``` 따라서 이번 보고서는 실제 provider 생성 품질을 검증했다고 주장하지 않는다. binary/SDK 설치 후에도 인증, 조직 권한, quota, model ID와 옵션 호환성은 live invocation으로 확인해야 한다. ## 11. 실제 private repository 접근 범위 이 검증 컨테이너에는 사용자가 지정한 다음 로컬 경로가 마운트되어 있지 않았다. ```text /home/donghyeon/workspace/ai-tool/llm-wiki-private ``` 대신 연결된 private GitHub repository에서 다음 문서를 선택적으로 확인해 설계 결함을 진단했다. - repository의 raw → canonical → external-output 규칙 - `feature-application-port-usecase-contract`의 D13 이유와 경계 - canonical package-layout의 현재 상태, Gradle/ArchUnit 검사, 정적 분석 한계 - logging decision record에서 SLF4J 선택 이유가 명시되지 않았다는 근거 경계 실행 검증은 재현 가능한 최소 corpus fixture로 수행했다. 실제 로컬 저장소 전체를 대상으로 한 end-to-end live provider run은 이 환경에서 수행하지 않았다. ## 12. 확인된 제한 - local corpus 검색은 lexical ranking이며 동의어와 간접 표현을 놓칠 수 있다. - 검색된 chunk가 source-backed라는 사실과 해당 문장이 최종 글에서 정확하다는 사실은 다르다. - canonical과 branch-note가 충돌할 때 완전한 자동 authority 판정은 하지 않는다. - 한국어 rationale lint는 휴리스틱이며 false positive/negative 가능성이 있다. - `STYLE001`은 가까운 세 문단의 서수 시작을 탐지하는 휴리스틱이다. 전체 문체 품질이나 개별 서수 표현의 적합성을 증명하지 않는다. - LLM reviewer 합의는 사실 증명이 아니다. - 코드 예제와 명령은 실제 대상 시스템에서 별도로 실행해야 한다. - Windows PowerShell script는 제공하지만 이 Linux 검증 환경에서는 실행하지 않았다. - 실제 게시 전에는 프로젝트 소유자, 보안 담당자, 운영 담당자의 검토가 필요하다. ## 13. 재현 명령 ```bash python3 -m venv .venv . .venv/bin/activate python -m pip install -e . bash scripts/verify.sh ``` 실제 provider 환경 진단: ```bash claridoc doctor --config config/pipeline.multi-agent.example.json ```