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:
DongHyeonka
2026-08-07 14:24:02 +09:00
co-authored by Claude Opus 5
parent 7dae5a9359
commit ef1f76146e
351 changed files with 0 additions and 32676 deletions
-165
View File
@@ -1,165 +0,0 @@
# Architecture
## 1. 목표
ClariDoc은 문장 생성 능력보다 다음 제어 계층을 우선한다.
1. 독자 과업과 문서 유형 계약
2. 프로젝트 근거의 수집과 source hierarchy
3. 기술 선택의 rationale completeness
4. 독자용 prose와 내부 provenance의 격리
5. 결정적 검사와 독립 reviewer
6. 재현 가능한 artifact와 hash manifest
## 2. 구성요소
```text
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/collect/validate/outline/lint/run/doctor
```
## 3. 입력 계층
### 3.1 Brief
Brief는 주제보다 독자 과업과 판단 경계를 먼저 고정한다.
- audience / prior knowledge / needs
- reader goal / core message
- scope / non-scope
- prerequisites / required topics
- citation style / date policy / style profile
- forbidden claims
### 3.2 SourcePack
Source는 단순 URL이 아니라 다음 metadata를 가질 수 있다.
```json
{
"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
}
```
이 metadata는 내부 reasoning과 audit에 사용된다. `citation_style=hidden`에서는 독자용 문서로 출력되지 않는다.
## 4. Local corpus retrieval
`corpus.py`는 다음 순서로 동작한다.
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으로 변환한다.
Source precedence:
```text
canonical-project
> canonical-concept
> branch-note
> official-doc
> company-tech-blog
> local-document
```
이 순서는 절대적인 진실 순위가 아니다. 현재 프로젝트 상태에는 canonical project가 우선이고, 선택 배경에는 branch note가 더 유용할 수 있다. Planner와 reviewer가 claim 종류에 맞게 사용해야 한다.
## 5. Outline contract
각 section은 다음 속성을 가진다.
```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는 제목·질문·근거 배치를 정교화할 수 있지만 intent의 삭제, 추가, 재배열은 할 수 없다.
## 6. Reader/provenance split
### Reader-facing surface
- `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 기록
-63
View File
@@ -1,63 +0,0 @@
# Extending ClariDoc
## 새 문서 유형 추가
1. `DocumentType`에 enum 추가
2. `STRUCTURE_SPECS`에 reader-question 순서 정의
3. procedural/example/trade-off lint 범주 검토
4. JSON Schema enum 업데이트
5. 각 intent가 unique하고 최소 section 수를 만족하는 테스트 추가
## 새 source type 추가
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 테스트 추가
## 새 reviewer 추가
Pipeline config의 reviewer role은 자유 문자열이지만 중복될 수 없다. role-specific prompt가 필요하면 `ROLE_GUIDANCE`에 추가한다.
추천 role:
- `editor`: 문장과 heading
- `security`: threat model과 secret exposure
- `api`: contract compatibility
- `domain-owner`: project-specific correctness
Model review response는 모든 `REVIEW_DIMENSIONS`를 포함해야 한다.
## 새 provider 추가
`Provider` interface를 구현한다.
```python
class MyProvider(Provider):
def generate(self, request: ProviderRequest) -> ProviderResponse:
...
def check(self) -> dict[str, object]:
...
```
요구사항:
- prompt는 stdin 또는 안전한 API body로 전달
- timeout 강제
- command/error를 audit event로 남길 수 있음
- cwd 복원과 output isolation
- credential을 response/event에 기록하지 않음
- fake executable 또는 fake SDK unit test
## Rationale lint 확장
현재 `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을 함께 추가한다.
-125
View File
@@ -1,125 +0,0 @@
# Logic model
## 1. 독자 질문의 순서
좋은 기술 글은 정보량보다 질문의 순서를 통제한다. 기술 블로그의 기본 질문은 다음과 같다.
```text
무슨 문제가 있었나?
왜 단순히 풀 수 없었나?
무엇을 검토했나?
왜 이 선택을 했나?
코드에서는 어떻게 동작하나?
무엇으로 확인했나?
어떤 비용과 한계가 남았나?
내 환경에서 무엇을 판단해야 하나?
```
제목은 이 질문에 대한 표지판이어야 한다. `개요`, `상세`, `기타`처럼 정보 역할을 드러내지 않는 heading은 경고 대상이다.
## 2. Decision unit
기술 선택은 다음 6요소를 하나의 논리 단위로 본다.
| 요소 | 질문 |
|---|---|
| context/constraint | 어떤 문제와 제약 아래에서 결정했는가 |
| choice | 무엇을 선택·허용·금지했는가 |
| why | 그 선택이 어떤 비용이나 위험을 줄였는가 |
| alternative | 현실적인 다른 선택은 무엇이었는가 |
| accepted cost | 선택 때문에 무엇을 감수했는가 |
| guardrail | 허용 범위가 넓어지지 않게 무엇이 실패하는가 |
“X를 의도적으로 사용한다”는 choice 하나만 있다. 이유가 없으면 `RAT001`, 대안·비용·가드레일이 없으면 `RAT002` 후보가 된다.
## 3. Evidence semantics
근거는 단어 일치가 아니라 claim role로 배치한다.
- **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
공식 문서가 `@Service`의 동작을 설명해도 프로젝트가 왜 그것을 선택했는지는 증명하지 않는다. 반대로 branch note가 선택 이유를 설명해도 현재 구현 상태가 바뀌었다면 canonical source를 확인해야 한다.
## 4. Status boundary
다음 status를 서로 바꾸어 쓰지 않는다.
```text
actually implemented
locally verified
production verified
documented only
planned
needs confirmation
unsupported
```
로컬 ArchUnit test 통과는 운영 효과의 증거가 아니다. 다른 회사의 사례는 이 프로젝트가 같은 결과를 얻었다는 증거가 아니다.
## 5. Concrete example
예시는 최종 코드 조각만 보여주지 않는다.
```text
initial state
→ input
→ decision criterion
→ selected path
→ state/control-flow change
→ observable result
→ success or recovery criterion
```
독자는 예시에서 추상 모델의 각 요소를 대응시킬 수 있어야 한다.
## 6. Korean problem-solving blog profile
`woowahan_tech_blog_ko` profile은 다음을 권장한다.
- 팀이나 시스템의 구체적 맥락에서 시작
- 기술 이름보다 문제와 비용을 먼저 설명
- 기존 방식, 실패한 시도, 대안을 숨기지 않음
- 선택 기준과 이유를 명시
- 구현 세부가 앞에서 세운 문제에 답하도록 구성
- 검증 결과를 원래 문제에 다시 연결
- project-local 결정을 보편 규칙으로 쓰지 않음
- 억지 접속어보다 문단 사이의 실제 논리 관계를 수정
- `문제 → 제약 → 대안 → 선택`을 의미 순서로 사용하되 문장 틀로 읽어 주지 않음
- 문단을 행위자, 상태, 변화, 결과, 판단에서 시작
- 질문형 heading은 바로 다음 문장에서 답하고, 접속어는 실제 인과·역접을 가리키게 함
- 순서어는 실제 단계·방법·레이어·도표에 사용하고, 추상 분류는 목록이나 의미 있는 소제목으로 표현
이는 샘플 글에서 관찰한 패턴을 하네스 규칙으로 번역한 것이며 공식 house style은 아니다.
특히 `첫 번째 제약은`, `두 번째 제약은`, `세 번째 제약은`처럼 outline의 분류명을 연속 문단 머리에 두는 방식은 정보 구조를 산문으로 노출한다. 한국어 기술 블로그에서 이런 형식이 가까운 문단에 세 번 이상 나타나면 `STYLE001` warning 대상이다. 실제 순서를 설명하는 번호 목록과 단계 문장은 대상이 아니다.
## 7. Date and citation logic
- access date는 provenance
- version/date가 behavior, compatibility, reproducibility를 바꿀 때만 본문에 사용
- hidden citation mode에서는 internal marker 금지
- public citation이 필요하면 footnote 또는 inline link 사용
## 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의 과장 여부
-58
View File
@@ -1,58 +0,0 @@
# Provider integrations
## Codex
기본 command:
```text
codex exec --sandbox read-only --output-last-message <file> -
```
Prompt는 stdin으로 전달한다. planner, logic reviewer, decision reviewer에 사용한다. `skip_git_repo_check``extra_args`는 provider option으로 설정할 수 있다.
## Claude
기본 command:
```text
claude -p --output-format text
```
Prompt는 stdin으로 전달한다. primary writer, reader reviewer, editor reviewer, reviser에 사용한다.
## Google Antigravity
Python SDK 표면:
```python
from google.antigravity import Agent, LocalAgentConfig
```
`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
claridoc doctor --config config/pipeline.multi-agent.example.json
```
`doctor`가 확인하는 것:
- CLI executable 또는 SDK import 가능 여부
- 설정된 integration surface
확인하지 않는 것:
- 로그인 유효성
- project/repository 접근 권한
- quota와 rate limit
- model ID availability
- 실제 response schema 안정성
## Mock
Mock provider는 deterministic fixture다. source excerpt를 최종 글에 복사하지 않으며, 외부 model을 호출하지 않는다. Mock reviewer score는 합성값이다.
-69
View File
@@ -1,69 +0,0 @@
# Security and trust boundaries
## 1. 주요 자산
- provider credential과 local authentication state
- private repository의 source text와 경로
- draft와 내부 decision record
- provider raw response와 event log
- 최종 독자용 문서
## 2. Prompt injection 경계
Brief, source chunk, title, URL, note, draft는 모두 untrusted data다. 모든 stage prompt는 source 내부 지시를 따르지 말고 내용으로만 취급하도록 명시한다.
완전한 prompt-injection 제거를 보장하지 않는다. 민감한 저장소에서는 다음을 권장한다.
- provider가 읽어도 되는 corpus root만 지정
- `--source-include`로 최소 directory만 허용
- secret, credential, production dump를 corpus에 포함하지 않음
- provider CLI의 sandbox와 조직 정책 사용
- 최종 provenance artifact의 접근 권한 제한
## 3. Reader-facing data minimization
`citation_style=hidden`의 목적은 내부 근거를 없애는 것이 아니라 노출 표면을 줄이는 것이다.
독자용 문서에서 금지:
- 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로 취급해야 한다.
## 4. Command execution
- Codex 기본 설정은 read-only sandbox다.
- writer/reviewer prompt는 shell 실행이나 file mutation을 요구하지 않는다.
- `options.command`, provider binary path, extra args는 신뢰된 local config로만 설정한다.
- 사용자 또는 source text에서 command option을 동적으로 만들지 않는다.
## 5. Destructive content
문서 안에 `rm -rf`, `DROP DATABASE`, `kubectl delete`, `terraform destroy` 등 파괴적 command가 있으면 주변에 다음이 모두 필요하다.
- 영향 경고
- backup/checkpoint/recovery
- expected effect
- read-only verification
이 검사는 command가 실제 환경에서 안전하다는 보증이 아니다.
## 6. Provenance integrity
`manifest.json`은 run artifact의 byte size와 SHA-256을 기록한다. manifest 생성 이후 파일이 바뀌면 재검산에서 드러난다. 전자서명이나 원격 attestation은 제공하지 않는다.
## 7. Provider credentials
Credential을 repository, brief, source pack, event log에 저장하지 않는다. Codex/Claude CLI와 Antigravity SDK의 표준 인증 방식을 사용한다. `doctor`는 설치 가능성만 확인하며 로그인, 권한, quota를 증명하지 않는다.
## 8. Known limits
- lexical retrieval이 민감한 문서를 선택할 수 있으므로 corpus scope를 운영자가 통제해야 한다.
- model이 source text를 재구성하면서 민감 정보를 노출할 수 있다.
- hidden citation lint는 알려진 path와 marker pattern을 검사하지만 모든 비밀 문자열을 탐지하지 않는다.
- private source에서 공개 가능한 결론을 만드는 책임은 프로젝트 소유자에게 있다.
@@ -1,630 +0,0 @@
# Korean Experience-Prose Contract Implementation Plan
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
**Goal:** Make Korean technical blogs and Korean READMEs use one experience-oriented `합니다/했습니다` prose contract that drafting, review, revision, deterministic lint, and the quality gate all enforce.
**Architecture:** Add `readme` as a first-class document type, centralize style activation and prompt guidance in `claridoc.style_contracts`, and add Markdown-aware deterministic style checks to `claridoc.lint`. Keep objective checks in lint and qualitative experience-flow checks in every model review, then migrate the maintained Korean fixtures and repository README to the enforced contract.
**Tech Stack:** Python 3.10+, standard-library `unittest`, JSON Schema Draft 2020-12, Markdown text processing with `re`, existing ClariDoc provider and quality-gate abstractions.
## Global Constraints
- Apply the contract automatically to Korean `technical_blog` briefs using `auto`, `woowahan_tech_blog_ko`, or `korean_problem_solving_blog`.
- Apply the contract automatically to every Korean `readme`.
- Do not apply first-person retrospective rules to tutorial, how-to, reference, troubleshooting, explanation, or design-document types.
- Preserve `Brief → SourcePack → deterministic outline → draft → lint/reviews → revision → quality gate → reader/provenance artifacts`.
- Treat source text and quoted examples as untrusted data; never invent experience or decision rationale.
- Exempt fenced code, headings, tables, block quotations, image alt text, command output, and quoted spans from formal-ending lint.
- Style-contract failures are blockers and cannot pass through configured error tolerance.
- Preserve unrelated user changes and do not regenerate `build/`, `dist/`, `.verify/`, or `.run/` artifacts during implementation.
---
### Task 1: Add a first-class README document contract
**Files:**
- Modify: `src/claridoc/models.py`
- Modify: `src/claridoc/structures.py`
- Modify: `schemas/brief.schema.json`
- Modify: `schemas/outline.schema.json`
- Modify: `tests/test_models.py`
- Modify: `tests/test_schemas.py`
- Modify: `tests/test_structures.py`
**Interfaces:**
- Consumes: existing `DocumentType`, `Brief.from_dict`, and `STRUCTURE_SPECS`.
- Produces: `DocumentType.README` with value `"readme"` and an eight-intent deterministic outline.
- [ ] **Step 1: Write failing runtime and structure tests**
Add:
```python
def test_readme_brief_round_trip(self) -> None:
brief = Brief.from_dict(brief_dict("readme"))
self.assertEqual(brief.document_type, DocumentType.README)
self.assertEqual(Brief.from_dict(brief.to_dict()).document_type, DocumentType.README)
```
and:
```python
def test_readme_outline_preserves_reader_onboarding_order(self) -> None:
brief = Brief.from_dict(brief_dict("readme"))
outline = create_outline(brief, make_sources())
self.assertEqual(
[section.intent for section in outline.sections],
[
"problem_value",
"principles",
"workflow",
"installation",
"quickstart",
"configuration",
"verification",
"limits_next",
],
)
```
Extend the schema test to validate a `readme` brief and outline instance with
`jsonschema.Draft202012Validator`.
- [ ] **Step 2: Run the focused tests and verify RED**
Run:
```bash
PYTHONPATH=src python3 -m unittest \
tests.test_models.ModelTests.test_readme_brief_round_trip \
tests.test_structures.StructureTests.test_readme_outline_preserves_reader_onboarding_order \
tests.test_schemas.SchemaTests.test_readme_is_accepted_by_brief_and_outline_schemas -v
```
Expected: failures because `"readme"` is not in the runtime enum or schemas.
- [ ] **Step 3: Implement the README type and deterministic outline**
Add:
```python
class DocumentType(str, Enum):
...
README = "readme"
```
Add eight `SectionSpec` entries under `DocumentType.README` using the approved
intent order. Each section must have Korean and English titles, reader
questions, purposes, and concrete `must_include` fields. Add `"readme"` to the
two schema enums.
- [ ] **Step 4: Run the focused tests and verify GREEN**
Run the Step 2 command.
Expected: all three tests pass.
- [ ] **Step 5: Commit the model contract**
```bash
git add src/claridoc/models.py src/claridoc/structures.py \
schemas/brief.schema.json schemas/outline.schema.json \
tests/test_models.py tests/test_schemas.py tests/test_structures.py
git commit -m "feat: add README document contract"
```
---
### Task 2: Centralize the Korean experience-prose prompt contract
**Files:**
- Create: `src/claridoc/style_contracts.py`
- Modify: `src/claridoc/prompts.py`
- Modify: `tests/test_prompts.py`
**Interfaces:**
- Consumes: `Brief.is_korean`, `Brief.document_type`, and `constraints.style_profile`.
- Produces:
```python
KOREAN_EXPERIENCE_CONTRACT_ID = "korean_first_person_experience_v1"
def korean_experience_contract_applies(brief: Brief) -> bool: ...
def style_guidance(brief: Brief) -> str: ...
def mandatory_style_review_checks(brief: Brief) -> str: ...
def revision_style_protocol(brief: Brief) -> str: ...
```
- [ ] **Step 1: Write failing prompt propagation tests**
Replace the narrow ordinal-only prompt test with separate tests that assert:
```python
for prompt in (draft, review, revision):
self.assertIn("korean_first_person_experience_v1", prompt)
self.assertIn("저는", prompt)
self.assertIn("제가", prompt)
self.assertIn("했습니다", prompt)
self.assertIn("현재 동작과 기술 설명", prompt)
```
Add a Korean `readme` case with the same assertions, an English technical-blog
case that does not contain the contract ID, and a Korean `tutorial` case that
does not contain the contract ID. Assert that review asks whether first person
represents a real observation and revision asks for a whole-document recheck.
- [ ] **Step 2: Run prompt tests and verify RED**
Run:
```bash
PYTHONPATH=src python3 -m unittest tests.test_prompts -v
```
Expected: contract-ID and README propagation assertions fail.
- [ ] **Step 3: Implement the shared contract module**
Move the existing Korean technical-blog profile out of `prompts.py`. Return a
single provider-facing contract for the approved activation cases. Include:
```text
concrete starting point
→ initial expectation
→ observed difference
→ immediate term explanation
→ author action or decision
→ result, cost, or remaining limit
```
Require `했습니다` for performed or observed work and `합니다` for current
behavior. State that `저는/제가` must establish a supported experience, not
decorate an objective explanation. State that unsupported conversations,
emotions, failures, durations, results, and rationales are forbidden.
- [ ] **Step 4: Inject the shared contract into every provider stage**
Make planning and drafting call `style_guidance(brief)`. Add
`mandatory_style_review_checks(brief)` to the mandatory review section and
`revision_style_protocol(brief)` to the revision protocol. Keep ordinal-frame
guidance inside the shared contract so no abbreviated duplicate remains in
`prompts.py`.
- [ ] **Step 5: Run prompt tests and verify GREEN**
Run the Step 2 command.
Expected: all prompt tests pass.
- [ ] **Step 6: Commit prompt integration**
```bash
git add src/claridoc/style_contracts.py src/claridoc/prompts.py tests/test_prompts.py
git commit -m "feat: propagate Korean prose contract to providers"
```
---
### Task 3: Add Markdown-aware deterministic style lint
**Files:**
- Modify: `src/claridoc/style_contracts.py`
- Modify: `src/claridoc/lint.py`
- Modify: `tests/test_lint.py`
**Interfaces:**
- Consumes: `korean_experience_contract_applies(brief)` and Markdown text.
- Produces:
```python
@dataclass(frozen=True, slots=True)
class ReaderProseSegment:
text: str
line: int
h2_title: str | None
def reader_prose_segments(markdown: str) -> list[ReaderProseSegment]: ...
def plain_form_ending_locations(markdown: str) -> list[int]: ...
def first_person_metrics(markdown: str) -> dict[str, int | float | bool]: ...
```
and lint codes `STYLE002` and `STYLE003`.
- [ ] **Step 1: Write a failing formal-ending lint test**
Create a Korean experience-contract brief and a structurally valid document,
then replace one prose sentence with `현재 구현은 이 값을 사용한다.`. Assert:
```python
issues = [issue for issue in report.issues if issue.code == "STYLE002"]
self.assertEqual(len(issues), 1)
self.assertEqual(issues[0].severity, Severity.BLOCKER)
self.assertEqual(report.metrics["plain_form_ending_count"], 1)
```
- [ ] **Step 2: Run the focused test and verify RED**
Run:
```bash
PYTHONPATH=src python3 -m unittest \
tests.test_lint.LintTests.test_korean_experience_contract_blocks_plain_form_endings -v
```
Expected: `STYLE002` is absent.
- [ ] **Step 3: Implement minimal Markdown prose extraction and ending lint**
Track fenced-code state and current H2 while scanning lines. Exclude headings,
block quotations, tables, image-only lines, and command-output blocks. Remove
inline code, Markdown link targets, and paired quoted spans before matching
plain Korean declarative endings with a boundary that does not match `니다.`.
Consolidate all matches into one blocker and record the total count.
- [ ] **Step 4: Run the focused test and verify GREEN**
Run the Step 2 command.
Expected: the test passes.
- [ ] **Step 5: Write failing exclusion tests**
Build a document whose fenced code, heading, table cell, block quote, image alt
text, inline code, and direct quoted example contain `한다.` while reader prose
uses `합니다.`. Assert that `STYLE002` is absent and
`plain_form_ending_count == 0`.
- [ ] **Step 6: Run the exclusion test and verify RED**
Run:
```bash
PYTHONPATH=src python3 -m unittest \
tests.test_lint.LintTests.test_korean_style_lint_exempts_non_reader_prose -v
```
Expected: at least one exempt region is incorrectly counted until all
exclusions are implemented.
- [ ] **Step 7: Complete the exclusion parser and verify GREEN**
Refine `reader_prose_segments` only as needed for the failing examples. Do not
implement a general Markdown parser or add a dependency.
- [ ] **Step 8: Write failing first-person coverage tests**
Add tests for:
- no `저는/제가` in the opening;
- fewer than half of substantive H2 sections containing a marker;
- table-only and code-only H2 sections not entering the denominator;
- opening plus at least half of substantive sections passing.
Assert `STYLE003` is one consolidated blocker and that the metrics contain the
approved contract ID, counts, and coverage.
- [ ] **Step 9: Run coverage tests and verify RED**
Run:
```bash
PYTHONPATH=src python3 -m unittest \
tests.test_lint.LintTests.test_korean_style_lint_requires_first_person_opening \
tests.test_lint.LintTests.test_korean_style_lint_requires_major_section_coverage \
tests.test_lint.LintTests.test_korean_style_lint_ignores_non_prose_sections \
tests.test_lint.LintTests.test_korean_style_lint_accepts_compliant_experience_prose -v
```
Expected: missing `STYLE003` and metrics failures.
- [ ] **Step 10: Implement first-person metrics and verify GREEN**
Treat the first substantive reader-prose paragraph as the opening. Count each
substantive H2 at most once. Require an opening marker and
`marked_sections / substantive_sections >= 0.5`. If there are no substantive
H2 sections, let existing structure checks handle the empty document while
recording zero coverage.
- [ ] **Step 11: Run all lint tests**
```bash
PYTHONPATH=src python3 -m unittest tests.test_lint -v
```
Expected: style tests pass; fixture-dependent failures, if any, identify the
next migration task rather than being hidden.
- [ ] **Step 12: Commit deterministic enforcement**
```bash
git add src/claridoc/style_contracts.py src/claridoc/lint.py tests/test_lint.py
git commit -m "feat: block Korean prose contract violations"
```
---
### Task 4: Make maintained fixtures satisfy the enforced contract
**Files:**
- Modify: `src/claridoc/providers/mock.py`
- Modify: `examples/golden/application-core-spring-di-boundary.md`
- Modify: `tests/test_lint.py`
- Modify: `tests/test_pipeline.py`
- Modify: `src/claridoc/report.py`
**Interfaces:**
- Consumes: new style metrics and existing mock `draft`/`revise` stages.
- Produces: contract-compliant mock Korean technical-blog prose and quality
reports that expose the active style contract and metrics.
- [ ] **Step 1: Add failing mock-pipeline and report assertions**
In `test_end_to_end_mock_run_creates_auditable_artifacts`, assert:
```python
self.assertEqual(
result.rounds[-1].lint_report.metrics["style_contract"],
"korean_first_person_experience_v1",
)
self.assertIn("korean_first_person_experience_v1", report_text)
```
Add a pipeline test that supplies a provider document with a `STYLE002`
violation and sets `max_errors` above zero; assert `result.passed` is false and
the blocker appears in `quality-gate.json`.
- [ ] **Step 2: Run pipeline and golden tests and verify RED**
Run:
```bash
PYTHONPATH=src python3 -m unittest \
tests.test_pipeline \
tests.test_lint.LintTests.test_golden_application_core_example_has_no_material_lint_issue -v
```
Expected: the report omits style metrics and maintained fixtures fail the new
blockers.
- [ ] **Step 3: Update mock prose without weakening lint**
Revise the mock technical-blog generator so its opening and at least half of
its H2 sections use supported `저는/제가` experience transitions and all
reader-facing Korean sentences use `합니다/했습니다`. Preserve synthetic
fixture warnings and never describe mock prose as quality evidence.
- [ ] **Step 4: Migrate the golden document**
Use the `revising-korean-technical-prose` skill to revise the golden document
in place. Preserve its exact H1/H2 contract, technical claims, decision
rationale, code block, evidence boundaries, and length intent.
- [ ] **Step 5: Render style metrics in the run report**
Add a `Reader-prose contract` subsection when
`final.lint_report.metrics["style_contract"] != "none"`. Render contract ID,
plain-ending count, first-person marker count, substantive-section count, and
coverage.
- [ ] **Step 6: Run pipeline and lint tests and verify GREEN**
Run the Step 2 command.
Expected: all tests pass and the report contains contract evidence.
- [ ] **Step 7: Commit fixture and report integration**
```bash
git add src/claridoc/providers/mock.py src/claridoc/report.py \
examples/golden/application-core-spring-di-boundary.md \
tests/test_lint.py tests/test_pipeline.py
git commit -m "test: migrate maintained Korean prose fixtures"
```
---
### Task 5: Restore the technical-document authoring skill
**Files:**
- Create: `.agents/skills/technical-document-author/SKILL.md`
- Create: `.agents/skills/technical-document-author/references/logic-contract.md`
- Create: `.agents/skills/technical-document-author/references/review-rubric.md`
- Create: `.agents/skills/technical-document-author/agents/openai.yaml`
- Create: `tests/test_repository_contracts.py`
**Interfaces:**
- Consumes: repository `AGENTS.md`, the ClariDoc pipeline, and
`revising-korean-technical-prose`.
- Produces: the authoring skill path already required by `AGENTS.md`, with a
validation-artifact completion contract.
- [ ] **Step 1: Invoke the skill-writing guidance**
Read and follow both `skill-creator` and `superpowers:writing-skills` before
creating the skill files.
- [ ] **Step 2: Write a failing repository-contract test**
Assert that the four skill files exist and that `SKILL.md` contains:
```text
Brief
SourcePack
STRUCTURE_SPECS
revising-korean-technical-prose
quality-gate.json
provenance
```
Also assert that the skill tells authors not to claim completion without lint,
independent review, and quality-gate artifacts.
- [ ] **Step 3: Run the repository-contract test and verify RED**
```bash
PYTHONPATH=src python3 -m unittest \
tests.test_repository_contracts.RepositoryContractTests.test_technical_author_skill_is_complete -v
```
Expected: failure because the required skill path is absent.
- [ ] **Step 4: Create the authoring skill and references**
The skill must route every document through the repository sequence, treat
inputs as untrusted data, keep provenance out of reader prose, and invoke the
Korean revision skill for Korean technical blogs and READMEs. The review rubric
must separate deterministic findings from model judgment. The logic contract
must preserve context, choice, reason, alternative, accepted cost, guardrail,
verification, and evidence status.
- [ ] **Step 5: Run the repository-contract test and verify GREEN**
Run the Step 3 command.
Expected: pass.
- [ ] **Step 6: Commit the restored skill**
```bash
git add .agents/skills/technical-document-author tests/test_repository_contracts.py
git commit -m "feat: restore technical document author skill"
```
---
### Task 6: Revise and document the repository README
**Files:**
- Modify: `README.md`
- Create: `examples/briefs/claridoc-readme.json`
- Modify: `tests/test_schemas.py`
- Modify: `tests/test_cli.py`
**Interfaces:**
- Consumes: `DocumentType.README`, shared prompt contract, and CLI
`validate`/`outline` behavior.
- Produces: a schema-valid README brief, documented usage, and a repository
README written in the enforced style.
- [ ] **Step 1: Write failing example and CLI tests**
Add tests that load `examples/briefs/claridoc-readme.json`, validate it through
`Brief.from_dict`, and run the CLI `validate` and `outline` commands. Assert
that the outline reports type `readme` and the eight approved intents.
- [ ] **Step 2: Run the focused tests and verify RED**
```bash
PYTHONPATH=src python3 -m unittest \
tests.test_schemas.SchemaTests.test_examples_match_runtime_contracts \
tests.test_cli.CliTests.test_readme_brief_validates_and_outlines -v
```
Expected: failure because the README brief does not yet exist.
- [ ] **Step 3: Add the README brief fixture**
Create a Korean `readme` brief for ClariDoc with hidden citations,
`style_profile: "auto"`, the current project scope, and no invented operational
claims.
- [ ] **Step 4: Run the focused tests and verify GREEN**
Run the Step 2 command.
Expected: pass.
- [ ] **Step 5: Revise README in place**
Use `revising-korean-technical-prose` and its sentence-pattern reference.
Preserve commands, tables, links, diagrams, versions, source hierarchy,
provider descriptions, and safety statements. Convert reader-facing Korean
prose to `합니다/했습니다`, add supported `저는/제가` experience transitions,
and add a section describing:
- automatic activation for Korean technical blogs and READMEs;
- `STYLE002` and `STYLE003`;
- model-review responsibilities;
- a `readme` brief example and validation command.
- [ ] **Step 6: Scan the README contract**
Run a read-only scanner using `reader_prose_segments` and assert:
```text
plain_form_ending_count = 0
opening_has_first_person = true
experience_section_coverage >= 0.5
```
Review the diff to confirm facts, code blocks, links, and information order
remain intact.
- [ ] **Step 7: Commit README migration**
```bash
git add README.md examples/briefs/claridoc-readme.json \
tests/test_schemas.py tests/test_cli.py
git commit -m "docs: apply Korean prose contract to README"
```
---
### Task 7: Run regression validation and review the implementation
**Files:**
- Modify only files required by verified failures in the preceding tasks.
**Interfaces:**
- Consumes: all implemented tasks.
- Produces: test and review evidence with no regenerated user-owned build or
distribution artifacts.
- [ ] **Step 1: Run the full unit and integration suite**
```bash
PYTHONPATH=src python3 -m unittest discover -s tests -v
```
Expected: all tests pass.
- [ ] **Step 2: Run non-destructive contract commands**
```bash
PYTHONPATH=src python3 -m claridoc validate \
--brief examples/briefs/claridoc-readme.json \
--sources examples/sources/retry-policy-sources.json
PYTHONPATH=src python3 -m claridoc outline \
--brief examples/briefs/claridoc-readme.json \
--sources examples/sources/retry-policy-sources.json \
--output /tmp/claridoc-readme-outline.json
```
Expected: both commands succeed and the output uses `document_type: readme`.
- [ ] **Step 3: Inspect destructive verification scope**
Do not run `scripts/verify.sh` because it removes and rebuilds `.verify`,
`build`, `dist`, egg-info, and demo outputs that already contain user changes.
Run its non-destructive validation portions through the unit suite, schema
tests, CLI tests, JSON parsing, local-link scan, and an isolated wheel build in
`/tmp`.
- [ ] **Step 4: Run independent code review**
Use `superpowers:requesting-code-review` to inspect the final diff against the
design and plan. Resolve every blocker and error through a new failing test
before changing production code.
- [ ] **Step 5: Run verification-before-completion**
Use `superpowers:verification-before-completion`, rerun the full test suite,
README style scan, schema validation, and isolated package build, and record
the exact results.
- [ ] **Step 6: Finish the development branch**
Use `superpowers:finishing-a-development-branch`. Because the user explicitly
requested uninterrupted inline implementation on the current branch, do not
merge, push, or open a PR without a new explicit request.
@@ -1,292 +0,0 @@
# Korean Experience-Prose Contract Design
## Goal
ClariDoc must apply one enforceable Korean prose contract when it writes or
reviews a Korean technical blog or Korean README. The contract must preserve
facts and document structure while making the reader follow the author's
experience in consistent `합니다/했습니다` prose.
The change closes the gap between a skill file that describes the desired
style and a harness that currently neither passes that style to providers nor
checks it before returning `PASS`.
## Scope
The contract applies automatically to:
- a Korean `technical_blog` using `auto`, `woowahan_tech_blog_ko`, or
`korean_problem_solving_blog`;
- every Korean `readme`.
It does not force first-person retrospective prose onto tutorials, how-to
guides, references, troubleshooting guides, explanations, or design documents.
Those document types keep their existing style behavior.
The current repository `README.md` is part of the migration. Its factual
content, commands, links, tables, and overall information order remain intact,
but its reader-facing Korean prose is revised to the same experience-oriented
`합니다/했습니다` style.
## Considered Approaches
### Prompt-only guidance
Copy the skill text into the drafting prompt. This has the smallest code
change, but it leaves no objective proof that the writer or reviser kept the
rules. It would preserve the current failure mode in which one correction
causes another part of the document to regress.
### Opt-in style profile only
Require README authors to select a special `style_profile`. This avoids adding
a document type, but a missing configuration value silently disables the
contract. It also makes README structure masquerade as another document type.
### Shared contract with a first-class README type
Add `readme` to the document model and define one shared prose contract used by
prompts, lint, reviews, revisions, reports, and tests. This is the selected
approach because it makes activation explicit and lets deterministic and model
judgment checks cover different parts of the same contract.
## Architecture
### First-class README document type
`DocumentType.README` is added to the model and JSON schemas. Its deterministic
outline contains these intents in order:
1. `problem_value`: the concrete problem and why the project exists;
2. `principles`: the project behavior and boundaries readers must understand;
3. `workflow`: the end-to-end operating flow;
4. `installation`: prerequisites and installation;
5. `quickstart`: the smallest useful execution path and expected result;
6. `configuration`: the main configuration choices and their effects;
7. `verification`: how to verify success and diagnose common failure;
8. `limits_next`: evidence limits, unsupported claims, and the next relevant
action.
The planner may refine titles and evidence allocation, but it must preserve
these intents and their order just as it does for existing document types.
### Shared prose contract
A focused `claridoc.style_contracts` module owns activation and provider-facing
guidance. It exposes:
```python
def korean_experience_contract_applies(brief: Brief) -> bool: ...
def style_guidance(brief: Brief) -> str: ...
```
The returned guidance includes the same rules in every provider stage:
- open the document and major transitions from a concrete code, screen,
request, or problem the author encountered;
- show the initial expectation, then the observed difference;
- explain an unfamiliar term where it first becomes necessary;
- show what the author checked, selected, or changed;
- close the thread with the result, accepted cost, or remaining problem;
- use `저는` or `제가` where it establishes the experience, without repeating
it mechanically in every sentence;
- use `했습니다` for observed or performed work and `합니다` for current
behavior and technical explanation;
- never invent an emotion, conversation, failure, duration, result, or
technical rationale that the evidence does not support;
- preserve code, commands, identifiers, numbers, links, tables, diagrams,
claims, evidence status, and outline order.
The guidance describes the canonical paragraph pattern as form, not as facts
to copy:
```text
concrete starting point
→ initial expectation
→ observed difference
→ immediate term explanation
→ author action or decision
→ result, cost, or remaining limit
```
`drafting_prompt`, `review_prompt`, and `revision_prompt` all call this shared
module. No stage keeps a separate abbreviated version.
### Deterministic checks
Deterministic lint checks only properties that can be recognized without
guessing the author's intent.
`STYLE002` reports a blocker when reader-facing prose mixes plain declarative
endings such as `한다.`, `있다.`, `아니다.`, or `~했다.` into a document whose
contract requires `합니다/했습니다`. Fenced code, headings, Markdown tables,
block quotations, image alt text, command output, and quoted spans are excluded.
The report consolidates matches and records their count and first locations.
`STYLE003` reports a blocker when the opening has no explicit `저는` or `제가`
marker, or when fewer than half of substantive H2 sections contain an explicit
first-person experience marker. A substantive section is an H2 section with at
least one reader-facing prose paragraph; code-only and table-only sections do
not count.
The lint report adds:
- `style_contract`: `korean_first_person_experience_v1` or `none`;
- `plain_form_ending_count`;
- `first_person_marker_count`;
- `experience_section_count`;
- `experience_section_coverage`.
Because both style issues are blockers, configured error tolerances cannot turn
them into a passing result.
Deterministic lint does not try to decide whether a paragraph contains a
genuine discovery, whether a term is unfamiliar, or whether the prose sounds
natural. Those require model judgment.
### Independent review and revision
Every reviewer role receives mandatory prose checks when the contract applies:
- the opening and major transitions follow an experience rather than listing
settled facts;
- the paragraph presents an actual expectation or observation rather than
inserting `저는` as decoration;
- unfamiliar terms are explained at first need;
- contrasts name the actual component and behavior that differ;
- the document does not manufacture personal history or project rationale;
- `합니다/했습니다` remains consistent outside exempt Markdown regions.
The revision prompt requires a whole-document contract audit after resolving
individual findings. This prevents a local rewrite from regressing another
section. Each revision round already runs lint and independent reviews again,
so the shared contract is re-evaluated before the quality gate can pass.
### Skill entry point
The dangling `.agents/skills/technical-document-author/SKILL.md` reference is
replaced with a real authoring skill. It preserves the repository sequence:
```text
Brief
→ SourcePack
→ deterministic outline
→ draft
→ lint and independent reviews
→ revision
→ quality gate
→ reader document and provenance artifacts
```
For Korean technical blogs and Korean READMEs, the authoring skill requires the
Korean prose contract and its sentence-pattern reference. It may not claim
completion without lint, review, and quality-gate artifacts. The existing
`revising-korean-technical-prose` skill remains the focused in-place revision
skill.
## Data Flow
```text
Brief(document_type, language, style_profile)
→ style-contract activation
→ planner keeps deterministic document structure
→ writer receives shared prose guidance
→ deterministic lint checks endings and first-person coverage
→ every reviewer checks experience quality and factual boundaries
→ reviser receives the same guidance plus all findings
→ lint and reviews run again
→ blockers prevent PASS
→ report records style metrics and findings
```
## README Migration
The repository `README.md` is revised in place with the
`revising-korean-technical-prose` skill:
- existing facts, code blocks, commands, paths, links, tables, and diagrams are
preserved;
- Korean reader-facing prose uses `합니다/했습니다`;
- the opening and major transitions explain how the harness's failure modes
were encountered and how the implemented workflow addresses them;
- no unverified personal event, advice, measurement, or project rationale is
added;
- a section documents the activation scope, lint codes, review behavior, and
`readme` brief usage.
The migration is checked separately from generated documents because the
repository README is not itself a pipeline output artifact.
## Error Handling
- Invalid `document_type: readme` handling disappears once the enum and schemas
are updated; other unknown types remain validation errors.
- Style lint returns actionable locations and correction guidance rather than
rewriting content.
- Empty or structure-only documents still fail existing structure and length
checks; style metrics do not mask those failures.
- Quoted evidence and code are excluded from deterministic ending checks so
original material is not altered to satisfy prose style.
- A model review cannot override a deterministic style blocker.
## Testing
Tests are added before production changes.
### Model and structure tests
- `readme` is accepted by `Brief` and outline schemas;
- `readme` receives eight unique required intents in the specified order;
- all existing document types retain their current outlines.
### Prompt tests
- Korean technical-blog and README draft, review, and revision prompts contain
the same contract identifier and required rules;
- English and unrelated Korean document types do not receive the contract;
- the revision prompt requires a whole-document recheck.
### Lint tests
- mixed `한다/합니다` prose is a blocker;
- fenced code, headings, tables, block quotations, image alt text, and quoted
examples do not cause false positives;
- missing opening first person is a blocker;
- insufficient substantive-section coverage is a blocker;
- a representative experience-oriented technical blog passes;
- a representative Korean README passes;
- unrelated document types retain existing lint behavior.
### Pipeline tests
- a style blocker prevents the quality gate from passing even when configured
error tolerance is nonzero;
- revision rounds receive the blocker and rerun the contract checks;
- final artifacts record the style contract and findings.
### Repository validation
- targeted unit tests are run after each TDD cycle;
- `PYTHONPATH=src python3 -m unittest discover -s tests -v` is run;
- `bash scripts/verify.sh` is run if it can preserve the user's unrelated
working-tree changes; otherwise its destructive build steps are inspected
and an equivalent non-destructive validation set is reported explicitly;
- the revised `README.md` is scanned outside code and quoted regions for plain
declarative endings and reviewed against the experience-flow checklist.
## Success Criteria
The implementation is complete only when:
- Korean technical blogs and Korean READMEs receive the contract in every model
stage;
- omitting `합니다/했습니다` consistency or first-person experience coverage
creates a deterministic blocker;
- qualitative experience flow is a mandatory independent-review concern;
- a revision cannot pass without rerunning the checks;
- `readme` is a supported contract-first document type;
- the missing technical-author skill entry point exists and requires validation
artifacts;
- the repository README follows and documents the same contract;
- all targeted and full regression tests pass.
@@ -1,46 +0,0 @@
# Runtime Call / Source Dependency SVG Split Design
## Brief
Split the two panels in `runtime-call-source-dependency.svg` into two standalone SVG assets. Do not change reader-facing Markdown or remove the existing combined SVG.
## Local evidence
- The combined SVG is a `1400 × 660` canvas with an upper runtime-call panel and a lower source-dependency panel.
- Identical assets exist in the generated run output and the golden fixture.
- Both corresponding documents currently reference the combined SVG.
- No maintained generator source for this asset exists in the repository; the metadata only names a historical `_work/regenerate-technical-assets.py` path.
## Output
Create these files in both asset directories:
- `runtime-call.svg`: the upper “실행 시점 관계” panel.
- `source-dependency.svg`: the lower “계약 소유·소스 의존” panel.
Each file will be a complete, independently renderable SVG with:
- a tightly fitted canvas and `viewBox`;
- its own accessible `<title>` and `<desc>`;
- only the marker definitions it uses;
- the same typography, colors, labels, nodes, and relationships as its source panel.
The existing `runtime-call-source-dependency.svg` remains unchanged for compatibility. Markdown references and alt text remain unchanged.
## Geometry
The panels will retain their original `1400`-unit width so horizontal proportions do not change. Vertical coordinates will be translated upward to remove the unused space belonging to the other panel. A small outer margin will be preserved around each panel.
The runtime-call asset will contain only `FeedController → GetFeedUseCase → SpringTransactionPort` and its solid-arrow labels. The source-dependency asset will contain only the interface, implementation, and dashed dependency relationships from the lower panel.
## Validation
- Parse all four new files as XML.
- Confirm each SVG has the expected root dimensions, `viewBox`, title, description, and referenced marker definitions.
- Confirm the runtime asset excludes lower-panel labels and the source-dependency asset excludes upper-panel labels.
- Confirm the golden and run-output copies are byte-identical for each new asset.
- Render or inspect both assets to catch clipping and layout regressions.
## Scope boundary
This change does not revise document prose, document image references, the existing combined asset, the technical-writing pipeline, or the asset-generation system.