312 lines
11 KiB
Markdown
312 lines
11 KiB
Markdown
# 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
|
|
```
|