chore!: remove ClariDoc harness
.run/의 세 런을 조사한 결과 claridoc run 파이프라인이 한 번도 완주하지 않았다. quality-gate.json 0건, stages/ 및 rounds/ 부재. 실사용 범위는 validate/collect/outline까지였고 글쓰기와 검수는 스킬이 담당했다. 파이썬 패키지, CLI, 스키마, 테스트, 예제, 조사 자료, 빌드·배포 산출물, 하네스 규약 문서를 제거한다. 남는 것은 Agent Skill 세 개, .run/의 문서 세 편, CLAUDE.md, README.md, LICENSE, 제거 결정 문서다. examples/golden의 구버전 초안 두 편(n+1liner.md 1416줄, claridoc-rewrite/document.md 1626줄)과 루트 document.md(.run 판과 md5 동일한 사본)도 함께 지운다. .run/에 더 진행된 판이 있다. 복구: git checkout pre-harness-removal -- <경로> 근거: docs/decisions/2026-08-07-remove-claridoc-harness.md Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
7dae5a9359
commit
ef1f76146e
@@ -1,10 +0,0 @@
|
||||
$ErrorActionPreference = "Stop"
|
||||
$Root = Split-Path -Parent (Split-Path -Parent $MyInvocation.MyCommand.Path)
|
||||
$env:PYTHONPATH = "$Root/src" + $(if ($env:PYTHONPATH) { ";$env:PYTHONPATH" } else { "" })
|
||||
$Out = "$Root/examples/output/retry-policy-demo"
|
||||
if (Test-Path $Out) { Remove-Item -Recurse -Force $Out }
|
||||
python -m claridoc run `
|
||||
--brief "$Root/examples/briefs/retry-policy-blog.json" `
|
||||
--sources "$Root/examples/sources/retry-policy-sources.json" `
|
||||
--config "$Root/config/pipeline.mock.json" `
|
||||
--output $Out
|
||||
@@ -1,10 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
export PYTHONPATH="$ROOT/src${PYTHONPATH:+:$PYTHONPATH}"
|
||||
rm -rf "$ROOT/examples/output/retry-policy-demo"
|
||||
python3 -m claridoc run \
|
||||
--brief "$ROOT/examples/briefs/retry-policy-blog.json" \
|
||||
--sources "$ROOT/examples/sources/retry-policy-sources.json" \
|
||||
--config "$ROOT/config/pipeline.mock.json" \
|
||||
--output "$ROOT/examples/output/retry-policy-demo"
|
||||
@@ -1,17 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
export PYTHONPATH="$ROOT/src${PYTHONPATH:+:$PYTHONPATH}"
|
||||
OUT_DIR="${1:-$ROOT/.run/application-core-mock}"
|
||||
|
||||
rm -rf "$OUT_DIR"
|
||||
python3 -m claridoc run \
|
||||
--brief "$ROOT/examples/briefs/application-core-spring-di-blog.json" \
|
||||
--source-root "$ROOT/examples/corpus/llm-wiki-mini" \
|
||||
--config "$ROOT/config/pipeline.mock.json" \
|
||||
--output "$OUT_DIR"
|
||||
|
||||
printf '\nGolden reader-facing example:\n%s\n' "$ROOT/examples/golden/application-core-spring-di-boundary.md"
|
||||
printf 'Retrieved evidence and mock provenance:\n%s\n' "$OUT_DIR/final/provenance.md"
|
||||
printf 'Note: the mock draft validates pipeline mechanics; the golden file is the curated prose example.\n'
|
||||
@@ -1,5 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
export PYTHONPATH="$ROOT/src${PYTHONPATH:+:$PYTHONPATH}"
|
||||
python3 -m unittest discover -s "$ROOT/tests" -v
|
||||
@@ -1,247 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
export PYTHONPATH="$ROOT/src${PYTHONPATH:+:$PYTHONPATH}"
|
||||
VERIFY_DIR="$ROOT/.verify"
|
||||
CORPUS="$ROOT/examples/corpus/llm-wiki-mini"
|
||||
GOLDEN="$ROOT/examples/golden/application-core-spring-di-boundary.md"
|
||||
APP_BRIEF="$ROOT/examples/briefs/application-core-spring-di-blog.json"
|
||||
DEMO_DIR="$ROOT/examples/output/retry-policy-demo"
|
||||
|
||||
rm -rf "$VERIFY_DIR"
|
||||
mkdir -p "$VERIFY_DIR"
|
||||
|
||||
printf '\n== Unit and integration tests ==\n'
|
||||
if python3 -c 'import coverage' >/dev/null 2>&1; then
|
||||
python3 -m coverage erase
|
||||
python3 -m coverage run --source="$ROOT/src/claridoc" -m unittest discover -s "$ROOT/tests" -v
|
||||
python3 -m coverage report -m | tee "$VERIFY_DIR/coverage.txt"
|
||||
else
|
||||
python3 -m unittest discover -s "$ROOT/tests" -v
|
||||
printf 'coverage package unavailable; coverage report skipped\n' | tee "$VERIFY_DIR/coverage.txt"
|
||||
fi
|
||||
|
||||
printf '\n== Contract and local-corpus validation ==\n'
|
||||
python3 -m claridoc validate \
|
||||
--brief "$ROOT/examples/briefs/retry-policy-blog.json" \
|
||||
--sources "$ROOT/examples/sources/retry-policy-sources.json"
|
||||
|
||||
python3 -m claridoc collect \
|
||||
--root "$CORPUS" \
|
||||
--query 'application-core Spring DI 선택 이유 대안 비용 가드레일' \
|
||||
--query 'TransactionPort spring-tx 금지 ArchUnit 검증' \
|
||||
--top-k 24 \
|
||||
--output "$VERIFY_DIR/application-core-sources.json"
|
||||
|
||||
python3 -m claridoc validate \
|
||||
--brief "$APP_BRIEF" \
|
||||
--source-root "$CORPUS"
|
||||
|
||||
python3 -m claridoc outline \
|
||||
--brief "$APP_BRIEF" \
|
||||
--source-root "$CORPUS" \
|
||||
--output "$VERIFY_DIR/application-core-outline.json"
|
||||
|
||||
python3 -m claridoc lint "$GOLDEN" \
|
||||
--brief "$APP_BRIEF" \
|
||||
--source-root "$CORPUS" \
|
||||
--json \
|
||||
--output "$VERIFY_DIR/application-core-golden-lint.json"
|
||||
|
||||
printf '\n== Offline end-to-end pipeline ==\n'
|
||||
bash "$ROOT/scripts/run-demo.sh"
|
||||
|
||||
printf '\n== Static, schema, provenance, and leakage checks ==\n'
|
||||
python3 - "$ROOT" "$VERIFY_DIR" <<'PY'
|
||||
from __future__ import annotations
|
||||
|
||||
import ast
|
||||
import hashlib
|
||||
import json
|
||||
import re
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
root = Path(sys.argv[1]).resolve()
|
||||
verify_dir = Path(sys.argv[2]).resolve()
|
||||
|
||||
python_files = sorted((root / "src").rglob("*.py")) + sorted((root / "tests").rglob("*.py"))
|
||||
for path in python_files:
|
||||
ast.parse(path.read_text(encoding="utf-8"), filename=str(path), feature_version=(3, 10))
|
||||
|
||||
ignored_parts = {"build", "dist", "__pycache__", ".git", ".verify"}
|
||||
json_files = [
|
||||
path
|
||||
for path in sorted(root.rglob("*.json"))
|
||||
if not any(part in ignored_parts for part in path.parts)
|
||||
]
|
||||
for path in json_files:
|
||||
json.loads(path.read_text(encoding="utf-8"))
|
||||
|
||||
schema_instances = 0
|
||||
try:
|
||||
import jsonschema
|
||||
except ImportError as exc: # pragma: no cover - verification environment diagnostic
|
||||
raise SystemExit(f"jsonschema is required by scripts/verify.sh: {exc}")
|
||||
|
||||
for schema_path in sorted((root / "schemas").glob("*.schema.json")):
|
||||
jsonschema.Draft202012Validator.check_schema(json.loads(schema_path.read_text(encoding="utf-8")))
|
||||
|
||||
pairs = [
|
||||
("schemas/brief.schema.json", "examples/briefs/retry-policy-blog.json"),
|
||||
("schemas/brief.schema.json", "examples/briefs/application-core-spring-di-blog.json"),
|
||||
("schemas/source-pack.schema.json", "examples/sources/retry-policy-sources.json"),
|
||||
("schemas/source-pack.schema.json", ".verify/application-core-sources.json"),
|
||||
("schemas/outline.schema.json", ".verify/application-core-outline.json"),
|
||||
]
|
||||
for schema_rel, instance_rel in pairs:
|
||||
schema = json.loads((root / schema_rel).read_text(encoding="utf-8"))
|
||||
instance = json.loads((root / instance_rel).read_text(encoding="utf-8"))
|
||||
jsonschema.Draft202012Validator(schema).validate(instance)
|
||||
schema_instances += 1
|
||||
|
||||
link_pattern = re.compile(r"\[[^\]]*\]\(([^)]+)\)")
|
||||
local_links = 0
|
||||
for path in sorted(root.rglob("*.md")):
|
||||
if any(part in ignored_parts for part in path.parts):
|
||||
continue
|
||||
for target in link_pattern.findall(path.read_text(encoding="utf-8")):
|
||||
target = target.strip().split("#", 1)[0]
|
||||
if not target or re.match(r"^[A-Za-z][A-Za-z0-9+.-]*:", target):
|
||||
continue
|
||||
local_links += 1
|
||||
resolved = (path.parent / target).resolve()
|
||||
if not resolved.exists():
|
||||
raise SystemExit(f"broken local Markdown link: {path.relative_to(root)} -> {target}")
|
||||
|
||||
collected = json.loads((verify_dir / "application-core-sources.json").read_text(encoding="utf-8"))
|
||||
sources = collected.get("sources", [])
|
||||
if not sources:
|
||||
raise SystemExit("local corpus collection produced no sources")
|
||||
first = sources[0]
|
||||
first_text = "\n".join(first.get("facts", []))
|
||||
if "수동 등록" not in first_text or "D13" not in first_text:
|
||||
raise SystemExit("decision-rationale chunk did not rank first")
|
||||
if Path(first.get("path", "")).is_absolute() or "/home/" in json.dumps(collected, ensure_ascii=False):
|
||||
raise SystemExit("collected evidence leaked an absolute path")
|
||||
if not any(item.get("source_type") == "canonical-project" for item in sources):
|
||||
raise SystemExit("local corpus did not retrieve canonical current-state evidence")
|
||||
if not any("SLF4J" in "\n".join(item.get("facts", [])) and "설명하지 않는다" in "\n".join(item.get("facts", [])) for item in sources):
|
||||
raise SystemExit("negative evidence boundary for unsupported SLF4J rationale is missing")
|
||||
|
||||
golden_lint = json.loads((verify_dir / "application-core-golden-lint.json").read_text(encoding="utf-8"))
|
||||
material = [item for item in golden_lint.get("issues", []) if item.get("severity") in {"blocker", "error"}]
|
||||
if material:
|
||||
raise SystemExit(f"golden example has material lint issues: {material}")
|
||||
|
||||
reader_docs = [
|
||||
root / "examples/golden/application-core-spring-di-boundary.md",
|
||||
root / "examples/output/retry-policy-demo/final/document.md",
|
||||
]
|
||||
forbidden = {
|
||||
"internal source marker": re.compile(r"\[(?:S|L)[A-Za-z0-9_-]+\]"),
|
||||
"evidence-pack narration": re.compile(r"제공된\s*(?:근거|자료)|근거\s*팩|확인\s*대상으로\s*제시"),
|
||||
"access-date boilerplate": re.compile(r"예시는\s*20\d{2}-\d{2}-\d{2}\s*기준"),
|
||||
"repository path": re.compile(r"(?:raw/branch-notes/|wiki/projects/|repo:///|/home/[^\s`]+)"),
|
||||
}
|
||||
for path in reader_docs:
|
||||
text = path.read_text(encoding="utf-8")
|
||||
for label, pattern in forbidden.items():
|
||||
if pattern.search(text):
|
||||
raise SystemExit(f"reader-facing leakage ({label}) in {path.relative_to(root)}")
|
||||
|
||||
if "SLF4J" in (root / "examples/golden/application-core-spring-di-boundary.md").read_text(encoding="utf-8"):
|
||||
raise SystemExit("golden reader-facing example invented or exposed unsupported SLF4J rationale")
|
||||
|
||||
run_dir = root / "examples/output/retry-policy-demo"
|
||||
run = json.loads((run_dir / "run.json").read_text(encoding="utf-8"))
|
||||
if not run.get("passed"):
|
||||
raise SystemExit("demo quality gate did not pass")
|
||||
if not any("synthetic" in warning for warning in run.get("warnings", [])):
|
||||
raise SystemExit("mock-run synthetic-score warning is missing")
|
||||
required_artifacts = {"document", "quality_report", "provenance", "evidence_map", "outline", "events"}
|
||||
if not required_artifacts.issubset(run.get("artifacts", {})):
|
||||
raise SystemExit("run.json is missing reader/provenance artifact separation")
|
||||
|
||||
manifest = json.loads((run_dir / "manifest.json").read_text(encoding="utf-8"))
|
||||
manifest_paths = {item["path"] for item in manifest["files"]}
|
||||
for required in {"final/document.md", "final/provenance.md", "final/evidence-map.json", "final/quality-report.md"}:
|
||||
if required not in manifest_paths:
|
||||
raise SystemExit(f"manifest missing required artifact: {required}")
|
||||
for item in manifest["files"]:
|
||||
artifact = run_dir / item["path"]
|
||||
if artifact.stat().st_size != item["bytes"]:
|
||||
raise SystemExit(f"manifest size mismatch: {item['path']}")
|
||||
digest = hashlib.sha256(artifact.read_bytes()).hexdigest()
|
||||
if digest != item["sha256"]:
|
||||
raise SystemExit(f"manifest hash mismatch: {item['path']}")
|
||||
|
||||
print(
|
||||
"STATIC VERIFIED: "
|
||||
f"{len(python_files)} Python files parse with Python 3.10 grammar; "
|
||||
f"{len(json_files)} JSON files parse; 5 schemas are valid and "
|
||||
f"{schema_instances} representative instances validate; "
|
||||
f"{local_links} local Markdown links resolve; corpus rationale ranking, "
|
||||
"reader/provenance separation, forbidden-phrase regression checks, and manifest hashes pass; "
|
||||
f"mock demo PASS at {run['final_score']:.1f}/100 (synthetic score)."
|
||||
)
|
||||
PY
|
||||
|
||||
printf '\n== Wheel build and clean-install smoke test ==\n'
|
||||
rm -rf "$ROOT/build" "$ROOT/dist" "$ROOT"/*.egg-info "$ROOT/src"/*.egg-info
|
||||
mkdir -p "$ROOT/dist"
|
||||
python3 -m pip wheel "$ROOT" \
|
||||
--no-deps \
|
||||
--no-build-isolation \
|
||||
--wheel-dir "$ROOT/dist" \
|
||||
>"$VERIFY_DIR/pip-wheel.log"
|
||||
WHEEL="$(find "$ROOT/dist" -maxdepth 1 -type f -name 'claridoc_harness-0.2.0-*.whl' -print -quit)"
|
||||
if [[ -z "$WHEEL" ]]; then
|
||||
echo "0.2.0 wheel was not produced" >&2
|
||||
exit 1
|
||||
fi
|
||||
(
|
||||
cd "$ROOT/dist"
|
||||
sha256sum "$(basename "$WHEEL")" > SHA256SUMS
|
||||
)
|
||||
|
||||
SMOKE_DIR="$(mktemp -d)"
|
||||
trap 'rm -rf "$SMOKE_DIR"' EXIT
|
||||
python3 -m venv "$SMOKE_DIR/venv"
|
||||
env -u PYTHONPATH "$SMOKE_DIR/venv/bin/python" -m pip install --force-reinstall --no-deps "$WHEEL" >"$VERIFY_DIR/pip-install.log"
|
||||
"$SMOKE_DIR/venv/bin/claridoc" --version | tee "$VERIFY_DIR/installed-version.txt"
|
||||
"$SMOKE_DIR/venv/bin/claridoc" validate \
|
||||
--brief "$APP_BRIEF" \
|
||||
--source-root "$CORPUS"
|
||||
"$SMOKE_DIR/venv/bin/claridoc" collect \
|
||||
--root "$CORPUS" \
|
||||
--query 'application-core Spring DI 선택 이유' \
|
||||
--top-k 8 \
|
||||
--output "$SMOKE_DIR/installed-sources.json"
|
||||
"$SMOKE_DIR/venv/bin/claridoc" lint "$GOLDEN" \
|
||||
--brief "$APP_BRIEF" \
|
||||
--source-root "$CORPUS" \
|
||||
--output "$SMOKE_DIR/installed-golden-lint.md"
|
||||
"$SMOKE_DIR/venv/bin/claridoc" run \
|
||||
--brief "$ROOT/examples/briefs/retry-policy-blog.json" \
|
||||
--sources "$ROOT/examples/sources/retry-policy-sources.json" \
|
||||
--config "$ROOT/config/pipeline.mock.json" \
|
||||
--output "$SMOKE_DIR/installed-demo"
|
||||
|
||||
printf '\n== Provider availability diagnostic ==\n'
|
||||
set +e
|
||||
python3 -m claridoc doctor \
|
||||
--config "$ROOT/config/pipeline.multi-agent.example.json" \
|
||||
>"$VERIFY_DIR/doctor.txt" 2>&1
|
||||
DOCTOR_STATUS=$?
|
||||
set -e
|
||||
cat "$VERIFY_DIR/doctor.txt"
|
||||
if [[ "$DOCTOR_STATUS" -ne 0 && "$DOCTOR_STATUS" -ne 3 ]]; then
|
||||
echo "doctor returned unexpected status: $DOCTOR_STATUS" >&2
|
||||
exit "$DOCTOR_STATUS"
|
||||
fi
|
||||
|
||||
printf '\nVERIFICATION COMPLETE\n'
|
||||
printf 'Wheel: %s\n' "$WHEEL"
|
||||
printf 'SHA-256: %s\n' "$(cut -d' ' -f1 "$ROOT/dist/SHA256SUMS")"
|
||||
Reference in New Issue
Block a user