chore: 문서를 작성할 때 한국어의 표현 작성 스킬 추가 및 1인칭 관점의 글 작성 검증 테스트 추가
This commit is contained in:
+230
-84
@@ -1,81 +1,149 @@
|
||||
# ClariDoc Harness 검증 보고서
|
||||
# ClariDoc Harness 0.2.0 검증 보고서
|
||||
|
||||
> 검증일: 2026-07-23
|
||||
> 대상 버전: `claridoc-harness 0.1.0`
|
||||
> 환경: Linux x86_64, Python 3.13.5
|
||||
> 호환성 계약: Python 3.10 이상
|
||||
- 검증 대상: `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. 판정
|
||||
## 1. 이번 수정에서 검증하려는 실패
|
||||
|
||||
소스 패키지, 오프라인 Mock 종단 간 파이프라인, 세 provider 어댑터의 격리 테스트, wheel 빌드·설치형 CLI를 검증했다.
|
||||
0.2.0은 단순한 기능 추가가 아니라 다음 회귀를 차단하는 수정이다.
|
||||
|
||||
**판정: 배포 가능한 개발자용 초기 버전.**
|
||||
1. 독자용 글에 source ID, 저장소 경로, 접근일, prompt 문장이 나타나는 문제
|
||||
2. “의도적으로 사용한다”는 선택 선언 뒤에 이유·대안·비용이 없는 문제
|
||||
3. 프로젝트의 branch-note와 canonical 문서를 검색하지 않고 일반론으로 이유를 채우는 문제
|
||||
4. 근거에서 이유를 확인하지 못한 SLF4J 선택을 그럴듯하게 설명하는 문제
|
||||
5. 독자용 문서와 내부 provenance가 같은 파일에 섞이는 문제
|
||||
6. `문제 → 제약 → 대안 → 선택 이유`라는 정보 구조가 `첫 번째 제약은` 같은 반복 문장 틀로 노출되는 문제
|
||||
|
||||
다만 Codex, Claude, Google Antigravity의 실제 실행 파일·SDK·인증이 이 검증 환경에 없으므로, 세 provider에 대한 **실제 모델 호출은 수행하지 않았다.** live 품질이나 계정별 모델 호환성을 증명하는 보고서가 아니다.
|
||||
검증 스크립트는 이 실패를 unit test와 별도의 artifact-level 회귀 검사로 모두 확인한다.
|
||||
|
||||
## 2. 자동화 테스트
|
||||
## 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
|
||||
bash scripts/test.sh
|
||||
PYTHONPATH=src python3 -m unittest discover -s tests -v
|
||||
```
|
||||
|
||||
결과:
|
||||
|
||||
```text
|
||||
Ran 31 tests
|
||||
Ran 44 tests
|
||||
OK
|
||||
coverage package unavailable; coverage report skipped
|
||||
```
|
||||
|
||||
검증 범위:
|
||||
주요 신규 회귀 테스트:
|
||||
|
||||
- 브리프, source pack, pipeline, outline, review 런타임 계약
|
||||
- 7개 문서 유형의 필수 intent와 순서
|
||||
- planner 구조 병합의 삭제·순서·출처 위반 차단
|
||||
- 리뷰의 9개 고정 평가 차원, severity, 유한 수치 검사
|
||||
- 빈 reviewer 목록, reviewer role 중복, 비정상 품질 게이트 차단
|
||||
- 필수 H2 누락·중복·순서 검사
|
||||
- 일반 source ID와 존재하지 않는 source marker 검사
|
||||
- 파괴적 명령의 영향 경고·복구점·검증 통제
|
||||
- reviewer role을 통한 artifact 경로 탈출 방지
|
||||
- Codex와 Claude의 가짜 실행 파일 기반 stdin/출력/인수 계약
|
||||
- Antigravity의 가짜 SDK 기반 설정 전달, async 응답, 작업 디렉터리 복구
|
||||
- Mock 종단 간 실행, 수정 한도, 품질 게이트, 이벤트, manifest
|
||||
- manifest 파일 크기와 SHA-256 재검산
|
||||
- CLI `init`과 `validate`
|
||||
- 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.py로 측정한 statement coverage는 **82%**였다. 이 수치는 테스트 범위의 보조 지표이며 정확성 증명으로 사용하지 않는다.
|
||||
이번 환경에는 `coverage` package가 없어 statement coverage를 다시 계산하지 않았다. Coverage 수치가 있더라도 사실 정확성이나 provider 품질을 증명하지는 않는다.
|
||||
|
||||
## 3. Python·JSON·문서 무결성
|
||||
## 4. Local corpus와 결정 근거 회수
|
||||
|
||||
```bash
|
||||
bash scripts/verify.sh
|
||||
fixture corpus는 실제 저장소 구조를 축소해 다음 경로를 포함한다.
|
||||
|
||||
```text
|
||||
wiki/projects/ca-tmpl
|
||||
raw/branch-notes
|
||||
raw/official-docs
|
||||
raw/company-tech-blogs
|
||||
```
|
||||
|
||||
검증 내용:
|
||||
검색 질의:
|
||||
|
||||
- 모든 `src/`와 `tests/` Python 파일을 Python 3.10 grammar로 파싱
|
||||
- 저장소 JSON 파일 구문 검사
|
||||
- 로컬 Markdown 상대 링크 해석
|
||||
- 예제 브리프와 source pack 런타임 검증
|
||||
- Mock 종단 간 실행
|
||||
- Mock 점수가 합성값임을 알리는 경고 존재
|
||||
- 예제 run manifest의 모든 크기와 SHA-256 재검산
|
||||
```text
|
||||
application-core Spring DI 선택 이유 대안 비용 가드레일
|
||||
TransactionPort spring-tx 금지 ArchUnit 검증
|
||||
```
|
||||
|
||||
별도로 Draft 2020-12 validator를 사용해 다음 인스턴스를 검증했다.
|
||||
회수 결과는 10개 heading chunk였으며, 1위는 다음 내용을 포함한 branch-note의 `결정 사항`이었다.
|
||||
|
||||
- 예제 brief → `brief.schema.json`
|
||||
- 예제 source pack → `source-pack.schema.json`
|
||||
- Mock pipeline과 multi-agent pipeline → `pipeline.schema.json`
|
||||
- 생성된 outline → `outline.schema.json`
|
||||
- 네 개의 raw reviewer 응답 → `review.schema.json`
|
||||
```text
|
||||
D13: @Service/@Component를 DI 등록 목적으로 허용
|
||||
이유: DI까지 제거하면 use case bean 수동 @Configuration 등록이 증가
|
||||
수용 비용: spring-context/spring-beans 의존
|
||||
경계: spring-tx, Spring Web, JPA 금지
|
||||
```
|
||||
|
||||
모두 통과했다. `jsonschema`는 검증 환경에서만 사용했으며 ClariDoc core runtime 의존성에는 포함하지 않았다.
|
||||
동시에 canonical project 문서에서 Gradle/ArchUnit 검사와 reflection-style bypass 한계를 회수했다. 수집 JSON에는 절대 경로가 없고 repository-relative path와 line range만 남았다.
|
||||
|
||||
## 4. 오프라인 종단 간 실행
|
||||
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
|
||||
@@ -85,75 +153,148 @@ bash scripts/run-demo.sh
|
||||
|
||||
```text
|
||||
GATE: PASS
|
||||
SCORE: 89.3/100
|
||||
SCORE: 95.6/100
|
||||
```
|
||||
|
||||
결정적 lint 점수는 `87.5/100`, blocker와 error는 각각 `0`이었다. 네 reviewer 점수는 모두 Mock fixture가 생성한 합성값이다. `run.json`과 품질 보고서에는 다음 경고가 자동 기록된다.
|
||||
세부 결과:
|
||||
|
||||
```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.
|
||||
```
|
||||
|
||||
따라서 이 PASS는 구조 계약, 린터, 리뷰 파싱, 게이트, artifact 배선이 동작했다는 의미다. 외부 모델의 문서 품질이나 예제 문서의 사실성을 의미하지 않는다.
|
||||
따라서 95.6점은 planner/writer와 logic·decision·reader·editor·evidence·operations reviewer, reviser 배선, 계약 파싱, lint, gate, artifact 생성이 동작했다는 의미다. 실제 모델의 문장 품질을 뜻하지 않는다.
|
||||
|
||||
## 5. Wheel 빌드와 깨끗한 설치
|
||||
## 7. Reader-facing 문서와 provenance 분리
|
||||
|
||||
빌드 artifact:
|
||||
Mock pipeline은 다음을 별도 생성했다.
|
||||
|
||||
```text
|
||||
dist/claridoc_harness-0.1.0-py3-none-any.whl
|
||||
SHA-256: 1dd71f73466a255e4a2a22d60482b6c1bc0e629de9d5b17110bcf4f0fb0b4cc6
|
||||
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. 새 가상환경 생성
|
||||
3. wheel을 `--no-deps`로 설치
|
||||
4. `claridoc --version`
|
||||
5. `claridoc validate`
|
||||
6. Mock provider `doctor`
|
||||
7. 설치된 CLI로 전체 Mock pipeline 실행
|
||||
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.1.0
|
||||
VALID: API 재시도는 횟수가 아니라 부하 예산으로 설계한다 (technical_blog), 3 sources
|
||||
GATE: PASS
|
||||
SCORE: 89.3/100
|
||||
claridoc 0.2.0
|
||||
validate: PASS, 10 sources
|
||||
collect: PASS, 8 evidence chunks
|
||||
lint: PASS
|
||||
mock run: PASS, 95.6/100
|
||||
```
|
||||
|
||||
## 6. Provider 검증 수준
|
||||
## 10. Provider 검증 수준
|
||||
|
||||
| Provider | 구현 표면 | 수행한 검증 | 실제 호출 |
|
||||
| Provider | 구현 표면 | 자동 테스트 | 현재 live 호출 |
|
||||
|---|---|---|---|
|
||||
| Codex | `codex exec`, stdin, `--output-last-message`, read-only sandbox | 가짜 executable로 command와 출력 수집 검증 | 미수행 |
|
||||
| Claude | `claude -p --output-format text`, stdin | 가짜 executable로 piped prompt와 stdout 검증 | 미수행 |
|
||||
| Antigravity | `google.antigravity.Agent`, `LocalAgentConfig`, async `chat` | 가짜 SDK로 config/model, cwd 격리, async text 검증 | 미수행 |
|
||||
| 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 응답 검증 | 미수행 |
|
||||
|
||||
실제 multi-agent config에 대한 `doctor` 결과는 exit code `3`이며 세 항목 모두 `MISSING`이었다.
|
||||
`doctor` 결과:
|
||||
|
||||
```text
|
||||
[MISSING] codex: codex exec
|
||||
[MISSING] claude: claude -p
|
||||
[OK] codex: codex exec
|
||||
[OK] claude: claude -p
|
||||
[MISSING] antigravity: google-antigravity SDK
|
||||
```
|
||||
|
||||
`doctor`는 설치 여부만 진단한다. 설치 후에도 로그인, 조직 권한, quota, 모델 ID, SDK 버전별 옵션은 live invocation으로 확인해야 한다.
|
||||
따라서 이번 보고서는 실제 provider 생성 품질을 검증했다고 주장하지 않는다. binary/SDK 설치 후에도 인증, 조직 권한, quota, model ID와 옵션 호환성은 live invocation으로 확인해야 한다.
|
||||
|
||||
## 7. 확인된 제한
|
||||
## 11. 실제 private repository 접근 범위
|
||||
|
||||
- source pack의 URL을 자동 방문하거나 사실을 자동 수집하지 않는다.
|
||||
- source marker가 존재해도 문장이 source fact를 정확히 함의하는지는 완전하게 증명하지 않는다.
|
||||
- LLM reviewer 간 합의는 진실의 증명이 아니다.
|
||||
- 코드 예제와 명령을 실제 대상 시스템에서 실행하지 않는다.
|
||||
- 한국어·영어 문장 길이와 문단 분리는 휴리스틱이다.
|
||||
- Windows용 `run-demo.ps1`은 제공하지만 이 Linux 환경에는 PowerShell이 없어 실행 검증하지 않았다.
|
||||
- 실제 게시 전에는 도메인 소유자 검토, 코드 실행, 보안 검토, 출처 원문 대조가 필요하다.
|
||||
이 검증 컨테이너에는 사용자가 지정한 다음 로컬 경로가 마운트되어 있지 않았다.
|
||||
|
||||
## 8. 재현 명령
|
||||
```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
|
||||
@@ -161,5 +302,10 @@ python3 -m venv .venv
|
||||
python -m pip install -e .
|
||||
|
||||
bash scripts/verify.sh
|
||||
```
|
||||
|
||||
실제 provider 환경 진단:
|
||||
|
||||
```bash
|
||||
claridoc doctor --config config/pipeline.multi-agent.example.json
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user