init: llm-wiki-haness 하네스 설계

This commit is contained in:
DongHyeonka
2026-07-24 14:21:35 +09:00
parent 42bf3db4fd
commit 6c53ded9cb
2436 changed files with 194486 additions and 1 deletions
+1
View File
@@ -0,0 +1 @@
# Reserved for the transactional vault migration.
+379
View File
@@ -0,0 +1,379 @@
# Advisory Depth Rule
This rule defines **how deep** an analysis, recommendation, brainstorm, concept explanation, or plan critique must go before the agent sends a response. It applies to:
- Multi-file wiki reports (research-lane, link-verifier, adversarial-reviewer).
- Direct-response answers when the controller did not dispatch a subagent.
- Brainstorming and design conversations about wiki structure, document policy, taxonomy decisions.
- Concept explanations and "explain X" questions (especially for `wiki/concepts/` extraction candidates).
- Plan gap reviews for wiki promotion pipelines (`/ingest`, `/projectize`, `/interviewize`, `/blogify`).
- Single-finding recommendations inside any of the above.
**Wiki scope:** 본 rule은 LLM Wiki 문서 작업의 자문 깊이를 강제한다. 코드(Java/CA) 자문의 동일 rule은 ca-tmpl `.agents/plugins/ca-superpowers/rules/advisory-depth.md` 가 처리한다 — 7 Contracts 의 골격은 동일하나 본 rule 의 예시·검증 명령·외부 인용 표준이 wiki 컨텍스트로 채워져 있다.
The user does not use this CLI to hear "this looks fine" or "this is a good idea". They use it for **practical engineering advice they could not produce alone**. Shallow advice is a failure even when the facts are correct.
## Core Contracts
The agent must satisfy all four contracts below on any qualifying response.
### Contract 1 — Goal → Assumption → Problem → Action Chain
Every finding, recommendation, or critique must be expressed as a causal chain with **explicit real-world assumptions** between the source text and the critique. The chain has seven required fields. None can be omitted.
```text
- **원래 목표 / Original goal:**
- 인용 / Verbatim quote: "<exact text, byte-for-byte from source>"
- 위치 / Source location: `<path>:<line>` (or `<path>:<startLine>-<endLine>` for ranges)
- 해석 / Interpretation: <agent's one-line restatement of what the quoted text intends>
- **현재 상태 / Current state:**
- 인용 / Verbatim quote: "<exact text, byte-for-byte from source>"
- 위치 / Source location: `<path>:<line>`
- 또는 / Or: "해당 라인 없음 — 명세에 명시되지 않음" (only when the gap is the absence itself)
- **실무 가정 / Real-world assumptions (NEW, REQUIRED):**
명시적 가정이 없으면 비판은 "에이전트가 상상한 구현"에 대한 비판이 되어 신뢰성을 잃는다.
최소 1개, 일반적으로 2~3개의 명시적 가정을 나열한다.
1. **가정 A:** <e.g., "implementation will be synchronous", "production scale > 1000 RPS", "team is using Kubernetes", "this branch will be implemented as-written">
- **무효 조건 / Falsifies if:** <under what concrete condition this assumption is false>
- **검증 방법 / How user can verify in their context:** <a specific check the user can run>
2. **가정 B:** ...
3. **가정 C:** ...
- **간극 / Gap (given the assumptions hold):**
- **구체적 실패 모드 / Concrete failure mode:** <X 상황에서 Y가 발생하여 Z가 깨진다>
- **재현 조건 / Reproduction condition:** <the trigger that actually exposes this in practice>
- **이 finding이 무효화되는 시나리오 / When this finding doesn't apply:** <if assumption A or B is false, this gap disappears — be explicit about which assumption is load-bearing>
- **필요 조치 / Required action:** <the specific action that closes the gap>
- **조치 근거 / Why this action:** <why this specific action (not a generic one) is correct here, given the stated assumptions>
- **대안 / Alternatives considered:** 3~5 enumerated per Contract 2.
- **반대 논거 / Counterarguments (NEW, REQUIRED — minimum 1, typical 2~3):**
이 권고를 적용하지 말아야 하는 시나리오, 또는 이 비판이 과장된 케이스를 명시한다.
자기 권고에 대한 self-critique이며, falsification 가능성을 더 폭넓게 확보하는 단계다.
1. **반대 A:** <이 권고가 틀릴 수 있는 시나리오, 또는 권고 비용이 효익을 초과하는 케이스>
- **반대 근거:** <왜 이 시나리오에서는 권고가 부적절한가>
- **사용자가 자기 환경에서 이 반대를 검증하는 방법:** <한 줄 체크>
2. **반대 B:** <또 다른 falsification 시나리오>
3. **반대 C:** ...
반대 논거가 0개라면 finding은 자동 `BLOCKED`. 자기 권고에 반대할 시나리오를 단 하나도 떠올리지 못한다면, 그 권고는 충분히 검증되지 않은 것이다.
```
A finding without a cited Original goal (verbatim + line) is `INFERENCE` and must be labeled as such. A finding without a concrete failure mode in Gap is opinion, not advice. **A finding without explicit Real-world assumptions is forbidden** — the agent must surface the implementation, scale, or context assumption that turns the spec text into a critique-worthy situation, so the user can immediately tell whether the assumption applies to their reality.
Bare findings like "성능이 떨어질 수 있다" or "고려가 필요하다" are forbidden. They must be expanded into a Gap with a named failure mode (for example, "스레드 풀 200 큐 + AbortPolicy → 큐 포화 시 RejectedExecutionException → outbox publish 손실").
### Why Assumption Surfacing matters
When the source text is ambiguous, in-progress (e.g., "검토", "TBD"), or stated at one level (e.g., "decision" vs. "implementation note"), the agent often imagines the worst-case implementation and critiques that. The critique then targets an imagined implementation, not the actual spec.
Examples of past failures this rule fixes:
- Spec says `"NTP drift > 5초 시 readiness fail 검토"` (line 116). Agent imagines `"synchronous NTP query inside the readiness probe"` and critiques DoS risk.
- **Without assumption surfacing:** the critique sounds authoritative but targets an imagined naive implementation.
- **With assumption surfacing:** the agent must write `"가정: 검토 단계에서 동기 호출로 구현될 것"`. The user immediately sees: "no, my plan is async — this critique doesn't apply" or "yes, I had not thought about sync vs async — this critique stands".
- Spec says `"management port 9001 분리"` and does not specify SecurityFilterChain. Agent imagines `"no filter chain configured, exposed to internet"`.
- **Without assumption surfacing:** "9001 포트가 무방비로 노출됨" — overconfident.
- **With assumption surfacing:** `"가정: 사용자가 management context를 위한 별도 SecurityFilterChain을 아직 구성하지 않았음"`. User: "아, 나 이미 구성했어" → critique no longer applies, no false alarm.
The rule is not to weaken critiques — it is to make critiques falsifiable. A critique whose assumption is wrong should be visibly rejectable in 5 seconds, not waste the user's time chasing a non-existent problem.
### Contract 2 — Decision-Relevant Option Coverage
When the user mentions any ordering, comparison, design choice, or "how should I do X", the agent must cover the **decision-relevant option space**, not only the option the user happens to have named. Factorial permutations that are equivalent under the same dependency constraints are not separate options.
Concrete rule of thumb:
- If the user names 1 ordering of N items, build the dependency DAG first. Identify blocking edges, reorderable groups, parallel groups, and skippable steps; compare only materially distinct topological schedules. Do not enumerate all `N!` permutations.
- If the user names 1 design approach, enumerate at least the canonical alternatives (typically 35).
- If the user asks "which library", enumerate the realistic candidates with their distinct trade-offs.
- If the user describes a workflow with N steps, list which steps can be reordered, which can be parallelized, which can be skipped, and which are blocking.
For each option in the enumeration, the response provides:
```text
- **케이스 / Case:** <one-line label>
- **적용 상황 / When it fits:** <the situations where this option is the right answer>
- **고려사항 / Considerations:** <what must be true / what must be watched>
- **장점 / Pros:** <concrete, not vague>
- **단점 / Cons:** <concrete, not vague>
- **비교 / Compared to others:** <how this differs from the other options in the same enumeration>
```
After enumerating, the agent provides a **conditional recommendation**, not a flat "use X". The form is:
```text
- If <situation A> → use <option α>, because <reason>.
- If <situation B> → use <option β>, because <reason>.
- If <situation C> → use <option γ>, because <reason>.
```
Flat recommendations like "X를 추천합니다" are insufficient. The agent always ties recommendations to situations.
### Contract 3 — Plan Gap Detection
When the user asks the agent to review, critique, or extend a plan document, the agent must explicitly identify:
1. **Tasks that should be in the plan but are not.** For each, give:
- Why it should be there (tied to the spec or original goal).
- Where it should slot in the order (before / after which existing step).
- What breaks if it is omitted.
2. **Tasks that are in the plan but should not be.** For each, give the reason for removal and the impact.
3. **Tasks whose ordering is wrong.** For each, give the corrected ordering and why.
4. **Implicit assumptions in the plan.** Surface them as explicit prerequisites.
A plan review that returns only "the plan looks good" is treated as `BLOCKED`. The agent must surface gaps or explicitly declare "no gaps found, all N tasks needed match the spec" with the matrix of plan-task → spec-section to prove it.
### Contract 4 — Direct-Response Template
When the controller answers a non-trivial advisory request directly (no subagent dispatch), the response uses a structured shape. The template scales with question size; only sections that materially help the decision are included.
```markdown
## 1. 질문 이해 / Question understood
- <한 줄 요약>
- 함의된 목표 / Implied goal: <what the user is actually trying to achieve>
- 함의된 제약 / Implied constraints: <budgets, deadlines, stack, scale; pulled from project context or asked if missing>
## 2. 경우의 수 / Option space
- <Option 1>
- <Option 2>
- <Option 3>
- ... (exhaustive per Contract 2)
## 3. 각 경우 분석 / Per-option analysis
### Case 1: <label>
- 적용 상황 / When it fits: ...
- 고려사항 / Considerations: ...
- 장점 / Pros: ...
- 단점 / Cons: ...
### Case 2: ...
## 4. 비교 표 / Comparison matrix
| Option | 적합 상황 | 주요 장점 | 주요 단점 | 비고 |
| --- | --- | --- | --- | --- |
(Required when there are 3+ options. Optional below that.)
## 5. 권고 / Conditional recommendation
- If <situation A> → <option α>, because ...
- If <situation B> → <option β>, because ...
(Flat "추천: X" is forbidden.)
## 6. 다음 결정 / Next decisions
- What the user must decide before the next step
- What information is still missing
- What questions the agent has for the user
```
For trivial single-fact questions (for example "이 메서드는 어디 있나요?"), answer with the fact and `file:line` citation only. Do not emit empty §2~§6 or `N/A` placeholders.
### Contract 5 — Citation Discipline
Every claim that names a specific number, setting, behavior, decision, or quotation must be backed by **verbatim quote + clickable file:line reference**. This applies to:
- §1 Executive Summary claims
- §2 Evidence Matrix "Extracted facts" column
- §4 Per-File Findings (every field that references the spec)
- §5 Priority Recommendations "근거 파일:라인" column
- Direct-response answers that reference any file
#### Verbatim quote rules
- **Byte-for-byte copy from source.** No paraphrasing, no normalization, no translation in the quote itself.
- If the quote is too long to embed inline (>200 chars), use elided form: `"<beginning 60 chars>" [...] "<end 60 chars>"` with the `[...]` marker explicit.
- If quoting Korean text from a source, keep it Korean. If quoting English, keep it English. Mixed-language sources are quoted as-is.
- The quote must contain the specific content that supports the claim. Quoting a tangential line and then drawing an unrelated conclusion is `FILENAME_INFERENCE` adjacent and counts as a citation failure.
#### Source link rules
- **Format:** `path/to/file.md:LINE` for a single line, `path/to/file.md:START-END` for a range.
- Paths are relative to the workspace root, not absolute (`/home/donghyeon/...` paths are forbidden in citations).
- IDE-clickable: `file:line` is the universal format that opens directly to the cited line in VS Code, IntelliJ, terminal grep results, GitHub, and most code review tools.
- For sources outside the workspace (e.g., external docs the user pointed to), still use `file:line` and include the absolute path in a separate `## Source roots` block at the top of the report.
#### Banned citation patterns
| Pattern | Why it fails | Replacement |
| --- | --- | --- |
| `근거: <file:line>` with no quote | User cannot tell if the cited line actually says what the agent claims | Always include verbatim quote alongside the line reference |
| `(L67)` style citations without the file path | Ambiguous when multiple files are discussed | Always include path: `feature-X.md:67` |
| Paraphrased "quote" rewritten in the agent's own words | Looks authoritative but is fabrication | Copy exact bytes from source. If clarity needed, add `해석:` field separately |
| `*근거: 위 문서 본문*` / vague references | Untraceable; impossible to verify | Specific file:line + verbatim quote |
| Quoting line N when the claim is about line M | Misdirection; the cited line doesn't actually support the claim | Quote the actual supporting line, or label as `INFERENCE` |
| Citing a non-existent line | Pure fabrication | Verify the line exists before citing |
#### Pre-send check (citation-specific)
송신 직전, 에이전트는 다음을 자기 draft에 대해 점검한다. 하나라도 실패하면 draft `BLOCKED`.
1. 모든 구체적 사실 주장에 대해 verbatim quote가 들어 있는가?
2. 모든 verbatim quote에 대해 `<path>:<line>` 형식의 위치 표기가 있는가?
3. 인용된 텍스트가 실제로 그 file:line에 존재하는가? (인용을 실행 가능한 grep 명령으로 검증할 수 있어야 한다)
4. 인용된 텍스트가 실제로 주장의 근거를 제공하는가? (탄젠셜한 라인 인용 금지)
5. 절대 경로 (`/home/...`) 가 아닌 워크스페이스 상대 경로인가?
6. 외부 디렉토리를 참조한 경우 §0 Source roots 블록에 절대 경로가 명시되었는가?
If a planned claim cannot be supported by a verbatim quote, the claim is removed or relabeled `INFERENCE` with an explicit note that no direct quote backs it.
### Contract 6 — Proof Manifest Verification
모든 verbatim quote는 `proof-request/v1``(finding.id, finding.role)`과 함께 넣고 `proof_runner.py`로 검증한다. 신규 run의 검증 SSOT는 inline shell transcript가 아니라 `proof-manifest/v1`이다. runner는 source 전체 SHA-256, line range, exact UTF-8 bytes와 finding-role 유일성을 확인한다.
source는 namespace를 명시한다.
- `namespace: repo``--repo-root` 아래의 저장소 자료
- `namespace: run``--run-root` 아래의 격리된 fetch·staging 자료
두 namespace 모두 상대 경로만 허용하며 각 root를 벗어나는 경로는 차단한다. report나 controller는 manifest의 경로·SHA-256·schema·proof/PASS/FAIL count를 `proof_hard_gate.py`로 다시 확인한다.
```bash
python3 harness/runtime/proof_runner.py '<proof-request.json>' \
--repo-root . --run-root '<run-root>' \
--output '<run-root>/proof-manifest.json'
python3 harness/runtime/proof_hard_gate.py '<run-root>/proof-manifest.json' \
--repo-root . --run-root '<run-root>' \
--manifest-sha256 '<sha256>' \
--proof-count '<N>' --pass-count '<N>' --fail-count 0
```
#### Pre-send check
1. draft에 남은 모든 quote가 request와 manifest에 존재하는가?
2. runner와 hard gate가 모두 exit `0`, status `PASS`인가?
3. `proof_count == pass_count`, `fail_count == 0`인가?
4. manifest path·hash·schema·count가 보고서의 §7.1과 일치하는가?
5. 실패 proof와 line correction은 모두 본문에 드러냈는가?
하나라도 실패하면 해당 finding을 제거하거나 보고서를 `BLOCKED`로 판정한다. 대표 PASS proof 1~3개는 가독성을 위해 펼칠 수 있지만, 표시 개수는 검증 count의 근거가 아니다. 전체 count는 persisted manifest와 standalone hard gate 결과만 소유한다.
### Contract 7 — Forbidden Marketing Words & External Evidence
Past failure: the agent's findings are mostly grounded, but the prose layered on top inflates them. Words like `"100%"`, `"완벽"`, `"극한"`, `"역사상 가장"` add no engineering meaning and signal that the agent is generating marketing copy on top of real analysis. Separately, claims of "well-known anti-pattern" or "industry standard practice" without an external citation are unverifiable appeals to authority.
This contract bans marketing inflation and forces external citations for industry-norm claims.
#### Banned phrases in advisory text
The following words and phrases are forbidden in §1 Executive Summary, §4 Per-File Findings, §5 Priority Recommendations, and Direct-Response answers. They are allowed only inside a verbatim quote (in which case they are accurately citing what the source actually said).
Marketing inflation:
- `100%`, `100점`, `0%` (as a perfection claim — `0 errors observed` is OK, `0%까지 완벽 보장` is not)
- `완벽`, `완벽히`, `완벽한`, `완벽무결`, `완전무결`
- `극한`, `극도`, `극단적`, `극심하게`, `극대화`
- `절대`, `절대적`, `절대로` (when used as universal quantifiers — `절대로 일어나서는 안 된다` is OK as a normative statement, `절대로 일어나지 않는다` as a factual claim is not)
- `최강`, `최고`, `최정상`
- `역사상 가장`, `사상 최고`, `세계 최초`
- `즉시`, `즉각` (when paired with hyperbolic claims like `즉시 다운`, `즉각 폭사`)
- `폭사`, `사살`, `섬멸` (사용자 환경에 대한 비유적 과장)
- `명품`, `초일류`, `엔터프라이즈급` (자기 평가)
Banned authority-appeals without citation:
- `well-known anti-pattern`, `standard practice`, `industry consensus`, `widely accepted`, `everybody knows`
- `대기업에서는`, `현업에서는`, `실무에서는` — when used to authorize a claim without a specific source. (Acceptable when the agent's own experience/reasoning is what's offered, but then the claim is `INFERENCE`, not authority.)
- `AWS/Google/Netflix가 이렇게 합니다` — without a specific public doc/talk URL or `CLAUDE.md` / `templates/<x>.md` cross-reference.
#### Replacement guidance
| Banned | Replacement |
| --- | --- |
| `100% 무결한 멱등성 보장` | `중복 결제 케이스 N개 차단. 잔여 엣지 케이스: <list>` |
| `완벽한 보안 격리` | `이 시나리오 하에서 격리됨. <Y> 시나리오는 별도 통제 필요` |
| `극한으로 깎인 스켈레톤` | `현재 명세 기준 N개 결함 식별, M개는 자동 검증 가능` |
| `즉시 폭사` | `<X초> 내에 응답 시간이 <Y배> 증가, 임계치 초과 시 알람` |
| `well-known anti-pattern` | 외부 문서 URL 인용 + 한 문장 인용. 인용 불가 시 `INFERENCE` 라벨 |
#### External evidence requirement
권고가 "이게 표준 / 업계 모범 / RFC / 공식 패턴이다" 라는 권위에 호소하면, 해당 권고는 다음 중 하나여야 한다.
1. **외부 문서 인용**: RFC, AWS/GCP/Azure 공식 문서, 공식 프레임워크 reference docs (Spring, Django, Rails 등), OWASP, 또는 명확한 저자가 있는 기술 블로그를 인용한다. URL 또는 문서 명칭(`RFC 8594`, `Spring Boot reference docs §6.4`, `OWASP Top 10 A03`, `Vaughn Vernon "Implementing DDD" Ch. 10` 등) 명시. 본 wiki의 `raw/official-docs/` 또는 `raw/company-tech-blogs/` 에 이미 발췌·보존된 자료라면 해당 raw 파일 wikilink + 원문 URL 동시 명시.
2. **LLM Wiki CLAUDE.md / templates/* / 기존 wiki 문서 인용**: 본 저장소가 자체적으로 채택한 결정 또는 정책이라면 그 결정 라인을 verbatim quote 로 인용 (예: `CLAUDE.md §15 파이프라인 강제`, `templates/linking-rules.md §2 Mandatory Upward Link 표`).
3. **INFERENCE 라벨**: 외부 근거가 없다면 권고를 `INFERENCE`로 라벨링하고, "제가 reasoning한 결과"라고 명시. 자기 추론은 합법적이지만 권위 호소로 위장하면 안 된다.
#### Pre-send check (Contract 7)
송신 직전, 에이전트는 자기 draft를 다음 기준으로 점검한다.
1. 금지 단어 grep: `egrep -oh '(100%|완벽|극한|극도|절대로|최강|역사상)' <draft.md>` 결과가 비어 있는가? (verbatim quote 내부 등장만 허용)
2. `well-known/standard practice/industry consensus/대기업에서는/현업에서는` 등의 표현이 등장한 곳마다 외부 문서 URL 또는 명세 인용이 함께 있는가?
3. 권위 호소가 있는데 인용이 없는 경우 해당 finding을 `INFERENCE`로 라벨링했는가?
위반 1건이라도 발견되면 draft는 `BLOCKED` 및 재작성.
## Concept Organization Mode
When the user asks for a concept explanation, terminology clarification, or "교통 정리" of an area they have not thought through, the agent uses this expansion of the direct-response template:
```markdown
## 1. 개념 정의 / Concept definition
- <짧고 정확한 정의>
- 흔한 오해 / Common confusions: ...
## 2. 구성 요소 / Components
- <subcomponents or related sub-concepts, each defined once>
## 3. 적용 / Where it applies
- <real situations where the concept matters in this project>
## 4. 대안 / Alternatives and adjacent concepts
- <other ways to model the same problem, with one-line trade-offs>
## 5. 이 wiki / 프로젝트에서의 적용 / How it applies here
- <link to CLAUDE.md / templates/<x>.md / 기존 wiki/concepts/<...>.md / 관련 raw/branch-notes 등 본 개념이 이미 등장하는 파일>
- <gaps in the current setup, if any>
## 6. 추천 학습 순서 / Suggested order to internalize
- <if the concept is layered, give the order to study its parts>
```
## Anti-Patterns
| Pattern | Why it fails | Replacement |
| --- | --- | --- |
| "X를 추천합니다" without conditions | User cannot tell when X is wrong | Conditional recommendation: "If A → X, if B → Y" |
| One option presented, no alternatives | User cannot tell what they are giving up | Exhaustive Option Enumeration (Contract 2) |
| "성능이 떨어질 수 있다" / "고려가 필요하다" | Vague worry, not advice | Name the concrete failure mode and trigger condition |
| Listing only the user's named ordering (1→2→3) | Hides valid dependency-aware alternatives | Derive the dependency DAG and compare materially distinct topological schedules |
| Plan review returning "looks fine" | No advisory value | Run Contract 3 explicitly, return gap matrix |
| Long mermaid diagram with no per-finding analysis | Decoration, not advice | Diagrams allowed only as supplement; the analysis carries the meaning |
| Finding without Original goal field | Cannot tell if this is critique or fabrication | Cite the spec/code line that states the original goal |
| Bilingual mirror response | User reads it twice | One language, the user's |
## Pre-Send Depth Check
Before sending any qualifying response, the agent runs this check against its own draft. If any item fails, the draft is `BLOCKED` and the agent rewrites.
1. Does every finding have all seven fields of the Goal → Assumption → Problem → Action chain (Original goal / Current state / **Real-world assumptions** / Gap / Required action / Why this action / Alternatives)?
2. Does every Original goal and Current state field include **verbatim quote + `<path>:<line>` location**, not paraphrase?
3. Does every finding have **at least 1 explicit Real-world assumption** with a falsification condition? Findings with 0 assumptions are forbidden — they critique imagined implementations.
4. Are all `<path>:<line>` citations real (matched against actual file content with verifiable grep), not invented?
5. Are verbatim quotes copied byte-for-byte from source (no paraphrasing inside the quote)?
6. If the user implied or asked about ordering, design choice, or comparison: are dependency constraints and all materially distinct alternatives covered without factorial permutation expansion?
7. For each enumerated option: are the 6 fields (Case, When-it-fits, Considerations, Pros, Cons, Compared) present?
8. Are recommendations conditional (`if X → α`), not flat?
9. If the response is a plan review: is the gap matrix present?
10. If this is a non-trivial direct response (no subagent): are the applicable §1~§6 sections present? If it is a trivial lookup, is the answer a concise fact plus citation without empty N/A sections?
11. Is the response in the user's language?
12. Is the response free of vague worries (`성능이 떨어질 수 있다`) and free of bare opinions (`고려가 필요합니다`)?
13. Are all citations using workspace-relative paths (no `/home/...` absolute paths)?
14. For external source directories outside the workspace, is there a §0 Source roots block at the top of the report mapping short names to absolute paths?
15. **Self-grep verification (Contract 6):** for every verbatim quote in the draft, did the agent actually run `sed -n '<line>p' '<file>'` or `grep -nF -- '<quote>' '<file>'` and observe the quote in the output? Quotes that were not verified — or were verified but did not match — must be removed or the finding `BLOCKED`. Citations are not honest until the command has been run.
16. **Verdict math (§3-1):** is the `Verdict:` label exactly the value computed by the §3-1 algorithm from (a)~(f) values in §3? Self-chosen labels that contradict the math are dishonest and force `BLOCKED`.
17. **Single-finding justification:** every §4 subsection with exactly 1 finding includes the mandatory justification block (단순 명세 / 전수 통과 + 1결함 / PARTIAL / 단일 critical) with concrete supporting facts (file line count, item list, etc.). Generic prose without facts → `BLOCKED`.
18. **Depth disclosure (§3 (f)):** if the count of §4 subsections is less than the count of `READ_FULL` + `READ_PARTIAL` rows in §2, are the missing files explicitly listed in the "분석 깊이 미달 파일 명세" table of §3 with reasons? Hiding the gap as "차이 0" while §4 lacks subsections is dishonest and forces `BLOCKED`.
19. **Counterarguments (Contract 1):** does every finding include at least 1 explicit Counterargument scenario (반대 논거) where the recommendation could be wrong or unnecessary, with a user-verification check? Zero counterarguments → `BLOCKED` (the agent has not self-critiqued).
20. **Forbidden phrases (Contract 7):** is the draft free of banned marketing words (`100%`, `완벽`, `극한`, `절대로`, `최강`, `역사상 가장`, `폭사`, `명품` etc.) outside verbatim quotes? Are authority appeals (`well-known`, `standard practice`, `industry consensus`, `대기업/현업에서는`) backed by RFC/official-doc citations or explicitly labeled `INFERENCE`? Violation → `BLOCKED`.
21. **Sampling honesty (Contract 6 sampling):** is `V` (검증한 quote 수) in §7.1 equal to the number of sed/grep commands actually written in §7.1? Not extrapolated from a small sample. Unverified quotes labeled `UNVERIFIED`, not "통과".
If the agent realizes mid-write that it cannot fill the Goal field for a finding (because the source spec was not actually read), it stops, marks that finding `INFERENCE`, and either reads the source or removes the finding. If the agent realizes it cannot state a clear Real-world assumption (because it does not actually know what assumption it is making), the finding is removed entirely — it was projection, not analysis. If the agent realizes the cited line does not contain the quoted text after running grep, the finding is removed entirely and any related Priority Recommendation referencing it is also removed. Apologies and confidence do not substitute for depth.
@@ -0,0 +1,66 @@
# rules/branch-depth-gate — 브랜치 노트 구현 착수 깊이 게이트
> `rules/` 의 방법론 규칙. branch-note 1개가 **코딩 착수해도 되묻지 않을 만큼 깊은가**를 판정한다.
> 이 문서는 **"전체 계약"이 아니다** — 전체 계약은 `raw/project-notes/ca-skeleton-operational-contract.md`.
> `feature-implementation-readiness-scorecard`(스켈레톤 adoption 거시 게이트)와 **다른 층·다른 범위**로 공존한다. 본 게이트는 *브랜치 노트 1개의 깊이* 미시 게이트.
## 적용
- 대상: `raw/branch-notes/feature-*.md` (구현 착수 전).
- 실행: `/depth <branch>`
1. **1차 결정론 검사** `.claude/hooks/wiki_structure_lint.py` (구조·링크 문법 — 싸고 빠름)
2. **2차 의미 판정** `branch-depth-auditor` (아래 4축 — 소스를 읽고 의미로 판정)
- 본 게이트는 **read-only**. 브랜치 노트를 편집하지 않으며 판정을 노트에 박지도 않는다.
## 역할 분담 (결정론 vs 의미)
| | 1차 린터(결정론) | 2차 감사기(LLM 의미) |
|---|---|---|
| R1 조사 깊이 | 링크 깨짐·앵커 부재만 | **claim 이 L0(존재)인지 L1+(메커니즘)인지** |
| R2 결정 조건 | `선택 조건`*비었는지* | 선택 조건이 *말이 되는지* |
| R3 구체 detail | 섹션/라벨 *존재* | detail 이 *충분한지* |
| R4 엣지·실패·의존 | 섹션 *존재* | 실패 경로가 *적절한지*, *암시된* 의존 포착 |
→ 2차 감사기는 **의미만** 본다(구조 존재는 1차가 이미 확인).
## 4축 (R1~R4)
> 축 라벨은 `R1~R4`. branch-note 의 Decision Evidence Map 이 `D1`,`D2` 를 *Decision ID* 로 쓰므로 `D*` 와 구분.
| 축 | Pass 조건 | Blocking(Not ready) 트리거 |
|---|---|---|
| **R1. 조사 깊이** | 각 Decision 의 Supporting Claim 이 깊이 사다리 충족 — 의존 메커니즘 L1+, 분기 조건 L2+ | 결정 근거 claim 이 순수 L0(존재만)뿐 |
| **R2. 결정 조건** | 각 Decision 이 "어떤 조건일 때 A, 아니면 B"의 선택 기준 명시 | `검토한 대안`은 있는데 *언제 그 대안을 고르는지* 기준 부재 |
| **R3. 구체 detail** | `## 구현 가이드` 의 각 in-scope 항목이 명명·경로·메커니즘·API/테스트명 구체화 **또는** `UNSUPPORTED_IMPL_DECISION` 라벨 + trade-off 한 줄 | in-scope 항목인데 구현 detail 도 UNSUPPORTED 라벨도 없음 |
| **R4. 엣지·실패·의존** | 실패/엣지 경로 열거 + 다른 contract 의존을 *대상 브랜치 + 그 Decision ID* 로 링크 | 정상 경로만 / 다른 계약 의존이 암시되는데 링크 안 됨 |
## R1 클레임 깊이 사다리
깊이의 단위는 **문서 개수가 아니라 결정별 종결**. 얕은 문서 10개 < 결정을 닫는 문서 1개.
| 레벨 | 클레임이 답하는 것 | 판정 |
|---|---|---|
| **L0 존재** | "X 가 있다 / 권장한다" | 단독 불충분 |
| **L1 메커니즘** | 어떻게 동작 / 언제 발생 | 메커니즘 의존 결정의 최소선 |
| **L2 조건·경계** | 언제 적용/제외, 실패 시 어떻게 | 분기 조건 있는 결정의 최소선 |
| **L3 검증** | 확인 방법·수치·반례 | 가산점 |
**출처 타입 적정성** (개수 기준 대체):
- 스펙/표준이 정의한 동작 → `official-standard`/`official-vendor-doc` 1개로 충분.
- "대기업은 보통 이렇게 한다" 운영 패턴 추론 → 회사 블로그 1개는 "공식" 불가. 독립 사례 2개+ 또는 official 1개 병행.
조사는 **결정-주도(top-down)**: 내려야 할 결정·미지수를 먼저 나열하고 각각을 닫을 때까지 조사. 조사 완료 = 모든 결정 종결 = 착수 가능.
## 판정 규칙
- 심각도 3단계: `Blocking`(Not ready) · `Should-fix`(권고) · `Advisory`(참고).
- **Ready = Blocking 0건.** Should-fix 가 남아도 사용자가 "감수" 선언 시 착수 가능(리포트에 기록).
- 모든 finding 은 4종 세트로 근거화: `심각도 · 위치(섹션/행) · 예상 의구심("구현 중 여기서 ___를 되묻게 됨") · 채울 방법`. 근거 없는 지적 금지.
## 명명된 실패 모드
- `EXISTENCE_ONLY` (R1): 결정 근거가 L0 뿐.
- `NO_SELECTION_CRITERION` (R2): 대안은 있으나 선택 조건 없음/무의미.
- `IMPL_UNDERSPECIFIED` (R3): in-scope 항목에 구현 detail·UNSUPPORTED 라벨 둘 다 없거나 불충분.
- `HAPPY_PATH_ONLY` (R4): 실패/엣지 경로 미열거.
- `IMPLICIT_DEPENDENCY` (R4): 다른 계약 의존이 암시되나 대상 브랜치/Decision ID 링크 없음.
@@ -0,0 +1,87 @@
# rules/consistency-contract — 문서 간 일관성 계약 (Single-Owner + Reference-Only)
> `rules/` 의 방법론 규칙. 문서 간 **모순의 근원은 재진술(복제)** 이다 — 같은 정책이 두 곳에 적혀 있으면 owner 쪽만 갱신될 때 모순이 *생산*된다. 본 계약은 재진술을 금지하고, 참조를 기계 검증하며, owner 변경을 역참조에 전파한다.
> 집행 3층: ① 결정론 검사기 `.claude/hooks/wiki_consistency_check.py` (Layer 1) ② `wiki-consistency-auditor` 의미 대조 (Layer 2) ③ `/sync` 수거 명령 (Layer 3).
## 원칙
| 원칙 | 내용 |
|---|---|
| **Single-Owner** | 모든 결정·관심사는 **정확히 1개의 owner 문서**를 가진다 — branch-note 의 Decision Evidence Map `D<n>` 행, 또는 project-note 의 `§<n>` 섹션. 같은 관심사를 두 branch 가 `covered-here` 주장하면 `DUAL_OWNERSHIP`. |
| **Reference-Only** | 타 문서는 owner 를 **포인터 + 1줄 요약**으로만 인용한다: `[[raw/branch-notes/<owner>]] D<n> — <1줄 요약>`. 정책 세부(임계값·메커니즘·예외 목록)의 재진술 금지 — 재진술은 owner 진화 시 낡은 복제본이 된다 (`RESTATED_FOREIGN_DECISION`). |
Project contract v2 에서는 project-note 의 Project Decision Registry 가 project-wide 결정 owner 다. ID 는 `DEC-<PROJECT>-<DOMAIN>-NNN`, revision 은 양의 정수이며 branch 참조는 항상 `DEC-...@revision` 으로 pin 한다. `<PROJECT>`·`<DOMAIN>` 은 uppercase kebab-case 다.
## 참조 형식 표준 (검사기 파싱 규약)
| 대상 | 형식 | 금지 |
|---|---|---|
| branch 결정 | `[[raw/branch-notes/<slug>]] D<n>` — wikilink **종료 후 같은 줄 100자 이내**에 `D<n>` | bare 슬러그 + D<n> (예: `feature-x-contract D7`) → `BARE_DECISION_REF` |
| project 섹션 | `[[raw/project-notes/<slug>]] §<n>` — 같은 줄 100자 이내 | 부재하는 § 번호 → `DANGLING_SECTION_REF` |
| Coverage delegated owner | owner 셀에 wikilink 필수 | bare 이름 → `BARE_OWNER_REF` |
| project 결정 | `DEC-<PROJECT>-<DOMAIN>-NNN@<positive-revision>` + `[[raw/project-notes/<slug>]]` | revision 없는 ID, 결정 상세 복제 |
| project Work Item | `WI-<PROJECT>-NNN` | branch slug 만으로 project handoff 식별 |
- `D<n>` 토큰이 wikilink 에서 같은 줄 100자를 넘으면 검사기가 참조 엣지로 인식하지 못한다 — 링크 직후에 쓴다.
- fenced code block 내부는 검사 대상 아님 (예시/템플릿 허용).
## 명명된 실패 모드
| 코드 | 층 | 의미 |
|---|---|---|
| `DANGLING_DECISION_REF` | 결정론 (`wiki_consistency_check.py`) | `[[feature-B]] D17` 인데 B 의 결정 표에 D17 부재 (B 실존 시 — 노트 부재는 `BROKEN_LINK` 몫) |
| `BARE_DECISION_REF` | 결정론 | wikilink 없는 bare 슬러그 + `D<n>` — 기계 추적 불가 |
| `BARE_OWNER_REF` | 결정론 | Coverage delegated 행의 owner 셀에 wikilink 없음 |
| `DUAL_OWNERSHIP` | 결정론 | 같은 관심사(정규화 exact)를 두 branch 가 `covered-here` 주장 |
| `DANGLING_SECTION_REF` | 결정론 | `[[project-note]] §34` 인데 해당 § 헤더 부재 |
| `STALE_SUMMARY` | 의미 (`wiki-consistency-auditor`) | 참조의 1줄 요약이 owner D-row 의 현재 내용과 어긋남 (owner 진화 후 무통보 낡음) |
| `CONTRADICTION` | 의미 | 두 문서가 같은 사안에 대해 양립 불가한 진술 |
| `RESTATED_FOREIGN_DECISION` | 의미 | 타 owner 의 결정 세부를 포인터 없이/포인터와 함께 본문에 재진술 (복제) |
| `MISSING_PROJECT_BINDING` | 결정론 | `project-work-item`의 slug가 WI row와 다르거나, `branch-child`의 parent·project·work_item 상속이 누락/불일치/순환임 |
| `MISSING_INHERITED_DECISION` | 결정론 | Work Item `Applies Decisions` 의 pinned ref 가 branch `inherits` 또는 Contract Packet 에 없음 |
| `STALE_INHERITANCE_REVISION` | 결정론 | branch 의 pinned revision 이 project registry 의 현재 decision revision 과 다르고 migration/override 로 설명되지 않음 |
| `CONFLICTS_WITH_PROJECT_DECISION` | 의미 | branch-local 결정·적용 요약이 inherited project decision 과 양립 불가하며 유효한 override 도 없음 |
| `UNDECLARED_OVERRIDE` | 결정론 + 의미 | project 결정과 다른 동작을 취하면서 `overrides` 와 Declared Overrides 표에 같은 pinned ref·이유·승인을 선언하지 않음 |
| `MISSING_EXPECTED_EDGE` | 결정론 | project→Work Item→branch, Work Item dependency, decision→branch inheritance 중 registry 가 기대하는 edge 가 없음 |
| `DUPLICATE_DECISION_OWNER` | 결정론 + 의미 | 같은 stable Decision ID 또는 같은 정규화 관심사를 둘 이상의 project/branch owner 가 소유함 |
| `DUPLICATE_BRANCH_ID` | 결정론 | 같은 stable Branch ID를 둘 이상의 v2 branch가 선언함 |
## Project → Work Item → Branch 상속 계약
1. project-note 가 `project_revision`, Project Decision Registry, Work Item Registry 를 소유한다.
2. Work Item row 는 적용 결정을 `DEC-...@revision` 으로 pin 하고 dependency 를 `WI-...` 로 가리킨다.
3. project 직접 자식 branch 는 `/branch-from-project` 로 만들며 frontmatter `project`·`work_item`·`inherits`·`depends_on``## Branch Contract Packet` 을 가진다.
4. branch 는 inherited 결정의 상세를 복제하지 않는다. project wikilink + pinned ref + project summary + branch application 만 기록한다.
5. branch-local 결정은 `D<n>` owner row 로 유지한다. project 결정을 refine 하면 `refines`, 다르게 적용하면 `overrides` 와 Declared Overrides row 를 함께 기록한다.
6. `kind: project-work-item`은 자기 slug가 Work Item Registry의 `branch slug`와 exact match여야 한다.
7. `kind: branch-child``parent_branch`가 필수이며 parent가 실존하고 cycle이 없어야 한다. child는 parent와 같은 `project`·`work_item`을 상속하고, Work Item row의 `branch slug`는 child가 아니라 parent `project-work-item` slug와 match한다.
8. `branch-child.inherits`는 parent inheritance + Work Item `Applies Decisions`의 superset이어야 한다. 제외는 같은 pinned ref가 frontmatter `overrides`와 승인된 Declared Overrides row 양쪽에 선언된 경우만 허용한다.
9. 직접 branch의 `id`는 Work Item ID의 `WI-``BR-`로 바꾼 값이다. child는 `BR-<PROJECT>-CHILD-<SHA256(slug) 앞 8자리>`를 사용하며 rename 뒤에도 ID를 재사용한다.
10. `planned`·`backlog`·`proposed`·`documented-only` Work Item은 branch 파일이 아직 없어도 expected-edge 실패로 보지 않는다. `in-progress` 이상 상태에서만 branch 실존을 요구한다.
archive로 격리한 문서는 active graph 검사에서 제외한다. active project/branch는 v2 계약을 적용하며 legacy 문서가 발견되면 `LEGACY_GRAPH_CONTRACT`로 이관 대상임을 보고한다.
## 전파
owner 노트의 D-row (결정 표) 가 변경되면:
1. **PostToolUse 훅이 역참조 목록을 비차단 알림** — 쓰기는 이미 완료, 모델에 "이 결정을 참조하는 문서 N개" 정보만 전달.
2. **같은 세션에서 참조 요약 갱신을 권장.** 변경이 D-row 의 의미를 바꿨다면 참조 측 1줄 요약이 낡았을 가능성이 높다.
3. 같은 세션에서 못 갱신한 항목은 **`/sync` 가 수거** (Layer 2 의미 대조 → fix-plan).
신규 참조 작성 시에는 PreToolUse 가 `DANGLING_DECISION_REF`/`DANGLING_SECTION_REF`**쓰기 차단** — owner 의 실제 Decision ID 를 확인하거나, 결정이 아직 없으면 owner 노트에 먼저 기록한다.
## 충돌 해소 우선순위
1. **owner 문서 우선** — 위임한 쪽(참조자)이 요약을 갱신한다. owner 본문을 참조자에 맞춰 고치지 않는다.
2. **hub(project-note) vs branch 충돌은 자동 적용 금지** — fix-plan 으로 사용자 판정. 보통 branch 가 더 최신·구체이므로 "project-note 갱신 제안" 형태가 기본이지만, 어느 쪽이 옳은지는 사용자가 정한다.
3. **적용은 항상 승인 후** — 어떤 해소도 사용자 확인 없이 본문을 바꾸지 않는다.
## retro 정책
- 기존 재진술·bare 참조는 **`/sync` 의 fix-plan 으로 점진 수거** — 일괄 자동 수정 금지. (2026-06 전수 dry-run: findings 190건 = `BARE_DECISION_REF` 129 · `BARE_OWNER_REF` 60 · 실제 `DANGLING_DECISION_REF` 1건 — D14 오귀속.)
- **신규 작성은 본 규약 준수** — 작성 시 참조 형식 가이드는 capture 계열(`/branch-spec` 등)이 본 문서를 참조한다.
## 한계 — 귀속 모호성
검사기는 외부 링크 후방 윈도의 `D<n>` 이 **인용자 자신의 DEM 에도 존재하면 침묵**한다 — 자기-결정 언급일 수 있기 때문 (실코퍼스: "X 에 의존 — 우회(D13)" 의 D13 이 인용자 자신의 D13). 따라서 결정론 층은 이런 케이스의 오귀속을 잡지 못하며, **의미 귀속 판정은 Layer 2 `wiki-consistency-auditor` 의 몫**이다.
+83
View File
@@ -0,0 +1,83 @@
---
title: rules / coverage-gate
source_type: reference
status: reviewed
tags: [rules, coverage, branch, ca-skeleton, quality-gate]
related_projects: [ca-skeleton]
last_reviewed: 2026-06-02
---
# coverage-gate — 브랜치 완전성 판정 기준
> 이 문서는 `/coverage` 명령(`.claude/commands/coverage.md`)과 `coverage-auditor` 서브에이전트(`.claude/agents/coverage-auditor.md`)의 **판정 기준 SSOT**다. `branch-depth-gate.md`(깊이)의 짝 — 이쪽은 **완전성(coverage)** 을 본다.
## Parent / 부모
- [[CLAUDE.md]] §11·§15 — 근거 없는 결정 금지, 근거 기반 구현 명세
- 짝 문서: [[rules/branch-depth-gate]] — 깊이 게이트
## 0. depth 와의 분업 (헷갈리지 말 것)
| 게이트 | 묻는 질문 | 비유 |
|---|---|---|
| `depth` (R1~R4) | 노트에 **적힌** 결정이 충분히 깊은가 | "네가 푼 문제는 잘 풀었나" |
| `coverage` (본 문서) | **적어야 할** 관심사가 다 적혔는가 | "안 푼 문제가 있나" |
→ coverage 는 *빠진 것*을 찾고, depth 는 *적은 것의 깊이*를 본다. 둘은 직교한다. 브랜치는 둘 다 통과해야 완성.
## 1. 기준의 출처 (reference standard 위계)
"무엇을 덮어야 하는가"는 **추측하지 않는다.** 다음 위계로만 판정:
1. **설계 문서 (1순위)** — 브랜치 frontmatter `governing_docs:` 가 가리키는 canonical 문서(`wiki/projects/ca-tmpl/<cluster>.md`). 이 문서가 열거하는 관심사가 "있어야 할 것"의 기준.
2. **선례(완성) 형제 브랜치** — 이미 구현된 브랜치들. 같은 관심사를 이미 누가 owner 인지 식별(겹치면 위임).
3. **ca-tmpl 실제 코드**`/home/donghyeon/workspace/ca-tmpl/src` + `docs/registries`. 관심사가 말로만 있는지 실제 구현인지 ground truth.
`governing_docs` 가 없으면 기준 부재 → 판정 불가(`NO_GOVERNING_DOC`, 1차에서 차단). 외부 taxonomy(OWASP 등)는 기준으로 삼지 않는다 — 기준은 프로젝트 자체 문서.
## 2. 상태 3종
각 관심사는 정확히 하나:
| 상태 | 의미 |
|---|---|
| `covered-here` | 이 브랜치가 결정으로 다룸 (Decision ID 보유) |
| `delegated` | 이 브랜치 밖이지만 다른 owner 브랜치가 소유 (위임 링크 필요) |
| `missing` | 어느 브랜치에도 결정으로 없음 |
## 3. 판정 (3단계 심각도)
| 신호 | 의미 | 트리거 (실패 모드) |
|---|---|---|
| 🔴 Blocking | 진짜 빠짐 | `MISSING_CONCERN` — governing 문서가 요구하는 관심사가 이 브랜치에도, 다른 owner 에도 없음 |
| 🟡 Should-fix | 위임 링크 누락 | `UNLINKED_DELEGATION` — sibling owner 가 있으나 본 노트(§Audit/§Coverage)에 위임 링크 없음 |
| ⚪ Advisory | 있으면 좋음 | governing 문서가 권고하나 핵심 아님 / `MIS-SCOPED_GOVERNING_DOC`(governing_docs 가 주제와 안 맞아 보임 — 한 줄 코멘트) |
| — | 정합 깨짐 | `STALE_OWNER` — §Coverage 가 가리키는 owner 가 코드/노트 대조상 실제로 그 관심사를 안 가짐 → 심각도는 갭 성격에 따라 |
**Covered = Blocking 0건.** Should-fix 가 남아도 사용자 "감수" 선언 시 통과(리포트 기록) — depth 와 동일.
## 4. 명명된 실패 모드
- `MISSING_CONCERN` (Blocking): governing 문서 관심사가 어느 브랜치에도 결정으로 없음. **이게 coverage 의 핵심 산출.**
- `UNLINKED_DELEGATION` (Should-fix): owner sibling 있으나 위임 링크 누락.
- `STALE_OWNER`: §Coverage 가 가리키는 owner 가 실제로 그 관심사를 안 가짐(코드/노트 대조 불일치).
- `NO_GOVERNING_DOC` (1차 차단): `governing_docs` 미지정 → 기준 부재로 판정 불가.
- `MIS-SCOPED_GOVERNING_DOC` (Advisory): governing_docs 가 브랜치 주제와 안 맞아 보임 — 적정성 의심을 surface(추측 단정 금지).
## 5. 판정 원칙
- **추측 금지** — governing 문서·선례 브랜치·코드를 *실제로 읽고* 판정. 안 읽고 "빠졌다/덮였다" 단정 금지.
- **owner 위임은 Blocking 아님** — 다른 브랜치가 소유하면 false block 하지 않는다. 위임 링크만 요구(Should-fix).
- **코드 ground truth 우선** — 노트가 "구현됐다"고 해도 `src/` 에 없으면 `STALE_OWNER` 또는 `missing`.
- 모든 finding 4종 세트: `심각도 · 관심사 · 상태(+owner) · 채울 방법`. 근거 없는 지적 금지.
- 자동 수정 금지(read-only). 갭은 `/branch-spec` 으로 되돌아가 채운다.
## 6. 프로젝트 모드 (`/coverage --project`)
- 전체 canonical 문서에서 관심사를 열거 → 각 브랜치 `## Coverage` 와 cross-ref.
- **owner-less 관심사**(아무 브랜치도 안 맡음) = 프로젝트 레벨 Blocking.
- 결과를 `wiki/projects/ca-tmpl/coverage-matrix.md`**생성**(손유지 금지 — 매 실행 재생성).
## 7. 면제
`governing_docs` 미지정 + `related_projects` 에 ca-skeleton/ca-tmpl 없는 브랜치(예: keycloak 학습 노트)는 coverage 면제. 1차 린터가 프로젝트 소속으로 판단.
+379
View File
@@ -0,0 +1,379 @@
---
title: LLM Wiki Diagram Standards (컨퍼런스급 — Minimalist-first)
source_type: meta
status: stable
tags: [meta, diagram-standards]
last_reviewed: 2026-05-26
version: 2
---
# LLM Wiki Diagram Standards — 컨퍼런스급
본 표준은 **대기업 기술 컨퍼런스(Toss SLASH, Kakao if(dev), Naver DEVIEW) 발표 슬라이드 수준** 의 다이어그램 기준이다.
> **핵심 원칙: 적을수록 좋다 (Less is more).**
>
> 컨퍼런스 발표 슬라이드를 다시 생각해보면 — 좋은 다이어그램은 **단순**하다. 박스 5~8개, 화살표 5~7개, 핵심만. 정보를 다이어그램에 몰아넣으면 청중은 어디부터 봐야 할지 모르고 패닉한다.
>
> 본 표준은 **"포함해야 할 것"** 이 아니라 **"포함하지 말아야 할 것"** 중심이다.
---
# 0. 도구 분리 (변경 없음)
| 다이어그램 종류 | 도구 | 저장 위치 |
|---|---|---|
| **시스템 아키텍처 / 정적 구조** | **draw.io XML** (`.drawio`) | `raw/diagrams/<project-slug>/` |
| **시퀀스 (시간축)** | **Mermaid `sequenceDiagram`** | 본문 inline |
| **ER (데이터 모델, 선택)** | **Mermaid `erDiagram`** | 본문 inline |
위반 시 자동 BLOCKED.
---
# 1. The Two Tests — 5초·30초 룰
다이어그램 1장은 두 시간 기준을 통과해야 한다.
### 5초 룰
청중이 슬라이드를 본 지 **5초 안에** 다음을 이해해야 한다:
- **이게 무슨 시스템인가** (제목 + 시각적 게슈탈트)
- **어디부터 봐야 하나** (진입점)
5초 안에 위 두 가지를 답할 수 없으면 다이어그램이 너무 복잡한 것이다.
### 30초 룰
발표자가 다이어그램을 설명하는 30초 동안 청중이:
- **데이터 흐름 + 핵심 결정 1개** 를 이해해야 한다
30초가 부족하면 다이어그램에 정보가 너무 많은 것. 분할 또는 단순화.
### 실패 신호
- 청중이 다이어그램 자체를 읽느라 발표자 설명을 못 들음 → 정보 과잉
- 청중이 "어디를 봐야 하나요?" 질문 → 진입점 불명확
- 청중이 5초 안에 색·박스·화살표 의미를 추측해야 함 → 컨벤션 위반
---
# 2. The Question — 1 다이어그램 = 1 질문
모든 다이어그램은 **하나의 질문에만 답한다.**
좋은 질문 (구체적·단일 초점):
- "P3A 패턴에서 사용자 요청은 어떤 컴포넌트를 거치는가?"
- "Outbox 패턴에서 DB와 broker 발행이 어떻게 원자적으로 분리되는가?"
나쁜 질문:
- "전체 시스템 구조" — 범위 너무 큼. 다이어그램 분할 필요.
**여러 질문이 있다 → 다이어그램을 분할한다.** 1 mega 다이어그램에 모든 걸 담는 건 부정직 (kitchen sink anti-pattern).
---
# 3. Element Budget — 요소 수 상한 (HARD LIMITS)
| 요소 | 권장 | 상한 | 초과 시 |
|---|---|---|---|
| **Vertex (박스)** | 5~7개 | **10개** | 분할 또는 비핵심 제거 |
| **Edge (화살표)** | 4~6개 | **8개** | 시퀀스 다이어그램으로 분리 |
| **Callout (주석 박스)** | 0~1개 | **1개** | 본문 텍스트로 옮김 |
| **Boundary group** | 1~2개 | **3개** | 중첩 단계 축소 |
| **Legend 항목** | 3~4개 | **6개** | 표준 컨벤션 사용 (legend 생략) |
| **색상** | 2~3 가지 (회색/흑백 + 강조 1) | **4 가지** | 색 분류 축소 |
상한을 초과하면 다이어그램이 잘못된 단위에 있다. 분할 또는 추상화 레벨 올리기.
---
# 4. Component Label — 박스 안 텍스트 ≤ 2줄
```
┌─────────────────────────┐
│ <Name> │ ← 1줄: 시스템 이름 (Bold)
│ <Context 1줄> │ ← 1줄: 역할 OR 기술. 둘 중 핵심만.
└─────────────────────────┘
```
예시:
| Bad (v2 스타일) | Good |
|---|---|
| `Spring Boot Resource Server`<br/>`Role: JWT 검증 + 비즈니스 API`<br/>`Stack: Spring Boot 3.4 / Java 21`<br/>`+ Spring Security 6.x`<br/>`Endpoint: localhost:8080`<br/>`Capacity: 1 instance`<br/>`Owner: 본인` (7줄) | `**Spring Boot RS**`<br/>`Spring Boot 3.4 · :8080` (2줄) |
**다이어그램에 안 들어가는 정보는 본문에**:
- 컴포넌트 상세 (역할, 책임, owner, capacity) → project-note 의 §"컴포넌트 책임 분담" 표
- 의존성 매트릭스 → 별도 §"외부 의존성" 표
- 운영 SLO → 별도 §"비기능 요구사항"
---
# 5. Edge Label — 화살표 라벨 ≤ 5단어
```
<step?> <verb/protocol> <object>
```
예시:
| Bad (v2 스타일) | Good |
|---|---|
| `① HTTPS GET / (HTML/JS)`<br/>` payload: ~50KB (initial SPA bundle)`<br/>` p99: ~80ms (cold) / ~10ms (cache)` (3줄) | `① GET /` (1줄) |
| `⑥ proxy_pass http://localhost:8080`<br/>` Authorization header forward`<br/>` (timeout: 30s, keepalive: 60s)` | `proxy_pass :8080` |
**스케일 어노테이션 (QPS, latency, payload size) 는 다이어그램의 질문이 *그것* 일 때만**:
- 일반 아키텍처 다이어그램: 화살표는 prototype + endpoint 만
- 성능 다이어그램: QPS / latency 가 핵심 → 그 때만 라벨에
번호 (①②③) 는 **순서가 중요할 때만**. 정적 토폴로지 다이어그램은 번호 불필요.
---
# 6. Visual Hierarchy Through Restraint — 색은 강조용
### 색 사용 비율
- **80% 회색/흑백** — 본문 박스의 기본 fill / stroke
- **15% 강조색 1개** — 다이어그램의 critical path 또는 primary system
- **5% 위험 / 경고색 (빨강)** — error path, SPoF, 보안 위협 — 있을 때만
### 표준 팔레트 (Minimal)
| 용도 | Fill | Stroke | 비고 |
|---|---|---|---|
| 일반 컴포넌트 (기본) | `#FFFFFF` | `#57606A` (회색) | 80% 의 박스가 여기 |
| **Critical path / 주인공** | `#FFFFFF` 또는 옅은 강조색 | **굵은 강조색** (`#1F6FEB` 파랑 또는 `#FB923C` 주황) | 다이어그램에서 가장 중요한 1~2개 박스만 |
| Data store (DB) | `#FFFFFF` | `#57606A` + cylinder shape | 모양으로 구분 |
| **External (점선)** | `#F6F8FA` | `#D0D7DE` (회색 점선) | 외부 시스템·3rd party |
| **Warning / Error path** | `#FEF2F2` (옅은 빨강) | `#DC2626` (빨강) | 있을 때만, 1~2 요소 한정 |
**금지**: 모든 박스에 색 칠하기. 색이 의미를 잃음 (color salad).
### Stroke 굵기
- 일반: 1~1.5px
- Critical path / Primary: 2~3px (강조용)
- Boundary: 1.5~2px
### 화살표 종류
| 종류 | 의미 |
|---|---|
| 실선 + 화살촉 | 동기 호출 (HTTP, RPC, JDBC) |
| 점선 + 화살촉 | 비동기 / fire-and-forget (Kafka publish, async event) |
| 굵은 실선 (2~3px, 강조색) | Critical path / hot path |
| 빨간 점선 | Error path |
화살표 종류는 **다이어그램 내 일관성** 이 핵심. 4종류 이상 섞지 말 것.
---
# 7. Boundary — 정보 있을 때만 사용
Boundary 는 **시각 장식이 아님.** 다음 중 하나일 때만 사용:
- **Trust Boundary**: 인증·인가 영역 분리 (파란 실선, 옅은 파란 배경)
- **Network Boundary**: VPC / 서브넷 / public-private (회색 점선)
- **External**: 외부 시스템 영역 (회색 점선)
### 금지
- 모든 컴포넌트가 1개 boundary 안에 있음 → boundary 가 정보 0. 제거.
- 3 단계 이상 중첩 boundary → 시각 복잡도 폭증
- "팀 소유권" 같은 다이어그램 핵심이 아닌 분류 → 다이어그램 외부 본문 표로
---
# 8. Callout — 1개만, 진짜 비자명한 것에만
Callout 박스는 **다이어그램의 시각 요소로 표현 불가능한 핵심 1가지** 에만 사용.
### 좋은 callout
- 비자명한 함정 (e.g., "KC_HOSTNAME 미설정 시 JWT iss mismatch")
- 핵심 결정의 이유 (e.g., "왜 BFF 대신 SPA-direct? — 학습 환경 단순성")
- 보안 위협 영역 (e.g., "JWKS unknown kid → DoS 벡터")
### 나쁜 callout (제거 대상)
- 단순 부가 정보 (capacity, version 등) → 박스 라벨로
- 컴포넌트 설명 → 본문 텍스트로
- "참고로..." 식 비핵심 메모 → 본문으로
**1개 이상의 callout → 다이어그램이 너무 많은 것을 말하려는 것. 분할.**
---
# 9. Legend — 표준 컨벤션이면 생략
Legend 는 **다이어그램 내 비표준 색·기호** 가 있을 때만.
### 표준 컨벤션 (Legend 불필요)
- 점선 = 외부 / 비동기
- Cylinder = DB
- Solid arrow = 동기 호출
- Dashed arrow = 비동기 / 점선 응답
### Legend 가 필요한 경우
- 다이어그램 내 색이 **§6 표준 팔레트 외** 인 경우
- 특수 기호 사용 (예: ⚡ for circuit breaker)
### Legend 작성 표준
- ≤ 6 항목 (가능하면 ≤ 4)
- 다이어그램 우하단 또는 본문 캡션
- 표준 컨벤션 (점선=외부, cylinder=DB) 은 legend 에 안 적음
---
# 10. Header / Footer — 미니멀
### Header (다이어그램 상단)
```
<Title>
<답하는 질문 1줄> ← 옵션
```
`Project / branch / status` 같은 메타 정보는 **다이어그램에 안 들어감**. project-note frontmatter 와 §3 본문에 이미 있음.
### Footer (다이어그램 하단)
```
v2 · 2026-05-26
```
작성자 / source wikilink / standard reference 같은 메타는 **다이어그램 외부**. project-note 의 frontmatter `diagrams:` 필드와 본문에서 참조.
---
# 11. Source 인용 — 본문에서, 다이어그램 안 X
핵심 사실의 출처 wikilink (`[[raw/official-docs/...]]`) 는 **다이어그램 옆 본문 또는 callout** 에 둔다. 화살표 라벨이나 박스 안에 wikilink 를 욱여넣지 말 것.
```markdown
![[architecture-p3a-...drawio]]
> **출처**:
> - KC_HOSTNAME 함정: [[raw/branch-notes/feature-keycloak-iss-claim-hostname-mismatch]]
> - redirect_uri 함정: [[raw/branch-notes/feature-keycloak-docker-compose-stack]]
> - OIDC PKCE: [[raw/official-docs/oauth2-pkce-rfc-7636]]
```
본문이 다이어그램을 보강한다. 다이어그램이 본문 역할까지 떠안지 말 것.
---
# 12. Mermaid Sequence — Minimal
- **메시지 ≤ 8개** (초과 시 분할)
- **`autonumber` 활성화**
- **에러 경로 1개** (alt/else)
- **트랜잭션 경계 1개** (Note over, 있을 때만)
- **지연·QPS 어노테이션 금지** (시퀀스의 질문이 *성능* 일 때만)
```mermaid
sequenceDiagram
autonumber
actor User
participant FE
participant API
participant DB
User->>FE: 로그인
FE->>API: POST /login
API->>DB: SELECT user
DB-->>API: row
alt 자격 증명 유효
API-->>FE: 200 + token
else 자격 증명 무효
API-->>FE: 401
end
```
이게 끝. `Note over` 도 비자명한 동작 1개에만.
---
# 13. Mermaid ER — Minimal
- **엔터티 ≤ 8개** (over-engineering 안 함)
- **PK / FK 표시 필수**
- **컬럼 ≤ 4개 per 엔터티** (모든 컬럼 X)
- **카디널리티 정확** (`||--o{` 1:N, `}o--o{` M:N)
- **관계 라벨 동사**
전체 스키마는 별도 ERD 도구 (DBeaver, dbdiagram.io) 로. project-note 의 ER 은 **핵심 엔터티 + 관계** 만.
---
# 14. Self-check — 컨퍼런스급 (재작성, 8항만)
다이어그램 작성 후 모두 ✓ 여야 발표 가능 수준.
- [ ] **5초 룰** — 5초 안에 "무슨 시스템인가" + "진입점" 이해 가능?
- [ ] **30초 룰** — 30초 발표로 흐름 + 핵심 결정 1개 전달 가능?
- [ ] **요소 수 상한** — Vertex ≤ 10, Edge ≤ 8, Callout ≤ 1, Legend ≤ 6?
- [ ] **단일 질문** — 다이어그램이 답하는 질문이 1개로 명확?
- [ ] **박스 라벨 ≤ 2줄, 화살표 라벨 ≤ 5단어?**
- [ ] **80% 회색/흑백 + 강조색 ≤ 2** ? (color salad 없음)
- [ ] **Boundary 정보 있을 때만** (장식용 boundary 없음)?
- [ ] **본문/캡션** 이 다이어그램을 보강 (다이어그램에 안 들어간 정보 본문에 있음)?
8/8 ✓ → 컨퍼런스 발표 가능. 1개라도 미달 → 다이어그램이 너무 많은 일을 하려는 것 → 분할 또는 단순화.
---
# 15. Anti-patterns — 절대 금지
| 안티패턴 | 증상 | 고치는 법 |
|---|---|---|
| **Kitchen sink** | 모든 정보를 다이어그램에 몰아넣음 (vertex 15+, edge 12+, callout 3+) | 분할 또는 본문으로 정보 이동 |
| **Color salad** | 모든 박스에 색 칠함. 색이 의미를 잃음 | 80% 회색/흑백, 강조 1~2개만 |
| **Legend bloat** | 사용된 모든 요소를 legend 에 → legend 가 다이어그램만큼 큼 | 표준 컨벤션은 legend 생략 |
| **Component bloat** | 박스마다 5+줄 텍스트 → 청중이 박스 하나 읽는 데 5초+ | 박스 2줄, 나머지는 본문 |
| **Edge label bloat** | 화살표마다 3줄 라벨 (QPS / latency / payload / step) | 1줄 5단어 이내 |
| **Callout salad** | 3+ callout 박스 → 어느 게 중요한지 모름 | 1개 (가장 중요한 함정만), 나머지 본문으로 |
| **Boundary nesting** | 3+ 중첩 boundary | 1~2 단계로 평면화 |
| **Numbered everywhere** | 모든 화살표에 번호 (필요 없는데도) | 순서가 중요할 때만 번호 |
| **Required-by-rule additions** | "표준이 시킨다고" 모든 칸 채움 → 필요 없는 정보 포함 | 표준의 목적은 *정보 전달*, 칸 채우기 X |
| **Scale annotation everywhere** | 모든 화살표에 QPS·latency | 다이어그램의 질문이 *성능* 일 때만 |
| **Mermaid `graph TD` 로 아키텍처** | 도구 선택 위반 | draw.io 사용 |
| **draw.io 로 시퀀스** | 도구 선택 위반 | Mermaid `sequenceDiagram` |
| **다이어그램이 본문 역할까지** | 다이어그램 안에 wikilink, 설명, 출처 다 들어감 | 다이어그램 = 시각 요약. 디테일·출처 = 본문 |
---
# 16. 컨퍼런스급 사례 (참고)
좋은 다이어그램의 공통점 (Toss SLASH / Kakao if(dev) / Naver DEVIEW 슬라이드 분석):
- 박스 5~8개 (10 초과 드묾)
- 박스 안 텍스트 1~2줄 (대부분 1줄)
- 화살표 라벨 1~5단어
- 색 2~3가지 (대부분 무채색 + 강조 1)
- Legend 종종 없음 (관례면 충분)
- **본문 / 발표자 설명이 다이어그램을 보강**
다이어그램은 발표자의 보조 도구 — 발표자의 입을 대체하지 않는다.
---
# 17. Quick Reference (작성 직전 빠른 체크)
```
□ 1 다이어그램 = 1 질문 (헤더에 명시)
□ 박스 ≤ 10, 화살표 ≤ 8, callout ≤ 1, legend ≤ 6
□ 박스 라벨 ≤ 2줄
□ 화살표 라벨 ≤ 5단어
□ 80% 회색/흑백, 강조색 ≤ 2개
□ Boundary 는 정보 있을 때만
□ 표준 컨벤션이면 legend 생략 (점선=외부, cylinder=DB)
□ 다이어그램 외부 본문에 출처 wikilink + 디테일
□ 5초 룰 + 30초 룰 통과
□ 박스 / 화살표 / 색 / 라벨 모두 컨벤션 일관
```
@@ -0,0 +1,152 @@
# Evidence-First Research Rule
This rule applies to every wiki research, document review, design critique, planning, audit, or task where the agent summarizes or evaluates files in this LLM Wiki repository.
**Wiki scope:** 본 rule은 `raw/`, `wiki/`, `templates/` 디렉토리의 마크다운 문서에 대한 evidence discipline을 강제한다. 코드(Java/CA) 작업의 evidence discipline은 ca-tmpl `.agents/plugins/ca-superpowers/rules/evidence-first-research.md` 가 처리한다 — 본 rule 과 핵심 원칙은 동일하나 subagent dispatch 대상이 다르다 (본 rule은 `wiki-research-lane`, ca-tmpl rule은 `ca-implementer`/`ca-architect-sentinel`).
## Prime Rule
> **A file is not "reviewed" until its body has been opened and inspected.**
Filenames, paths, titles, prior memory, and general expertise are not evidence. They produce hallucinated conclusions and dishonest reports.
## Rationalization Stop List
If the agent catches itself thinking any of the following, it must stop and either read the missing files or dispatch subagents. None of these thoughts are valid reasons to skip reading.
| If you are thinking... | The truth |
|---|---|
| "I can infer this from the filename, it is obvious." | That is `FILENAME_INFERENCE`. Not acceptable as a final finding. |
| "I remember roughly what is in this file from earlier." | That is `MEMORY_HALLUCINATION`. Memory of files is stale and not evidence. |
| "I am confident this is what the file says." | Confidence without a read is `CONFIDENCE_WITHOUT_READ`. Open the file. |
| "All these files probably follow the same pattern, I can answer for the batch." | That is `BATCH_ASSUMPTION`. Each file must be read or marked `NOT_READ`. |
| "Reading all of them will take too long, I will summarize from a few." | Split work across multiple Read calls. For document-heavy research, redirect to LLM Wiki (`wiki-research-lane`). There is no shortcut. |
| "The user only approved a few files, I will fill in the rest from training data." | Files outside the approved slice are `UNVERIFIED`. Report them as such, do not invent content. |
| "A quick high-level pass is good enough for now." | A high-level pass without evidence is not a finding, it is a guess. |
| "The user will not notice if I skip a few files." | The user always notices. Honesty about coverage is required. |
## Named Failure Modes
Use these exact labels when reporting on unread or under-read material:
- `FACT`: directly supported by file content, command output, or tool result.
- `INFERENCE`: reasoned from explicit facts. Must be marked `INFERENCE`, not stated as fact.
- `FILENAME_INFERENCE`: guessed from path or title only. Not acceptable as a final conclusion.
- `MEMORY_HALLUCINATION`: produced from prior memory of a file rather than a current read. Not acceptable.
- `CONFIDENCE_WITHOUT_READ`: stated with confidence but no read evidence. Not acceptable.
- `BATCH_ASSUMPTION`: extrapolated from a few files to a larger group. Not acceptable.
- `UNVERIFIED`: not read, not accessible, or not approved for reading. Acceptable as a status, never as a finding.
Any unread material that appears in a response must be presented as `NOT_READ` / `BLOCKED` / `UNVERIFIED`. It cannot be promoted to a conclusion.
## Approved Scope Discipline
If the user approved reading only N specific files, the agent reads exactly those N files and reports every other in-scope file as `NOT_READ`. The agent does not claim coverage of files outside the approved slice. The agent does not "fill in" content for files it could not open.
If the agent realizes that the approved slice is too narrow for the user's request, the agent surfaces this gap and asks for permission to expand the slice or to dispatch subagents. It does not proceed by guessing.
## Required Evidence Matrix
For any multi-file review, response must include:
```text
| Path | Status | Evidence | Extracted facts |
| --- | --- | --- | --- |
| raw/branch-notes/feature-keycloak-oauth2-proxy-oidc-flow.md | READ_FULL | lines 1-140 | OIDC handshake 흐름 정의, oauth2-proxy 결정 근거 |
| raw/official-docs/oidc-discovery-keycloak-official.md | READ_PARTIAL | lines 1-80, 220-280 | Discovery endpoint 명세만 정독, token-introspection 미정독 |
| raw/branch-notes/feature-keycloak-nginx-auth-request-integration.md | NOT_READ | not approved / not found | UNVERIFIED |
```
Allowed status values are exactly:
- `READ_FULL`: file body read end to end.
- `READ_PARTIAL`: only named sections or line ranges read.
- `NOT_READ`: file body not read.
- `BLOCKED`: file could not be read due to permission, path, tooling, or approval limits.
If any in-scope file is `NOT_READ` or `BLOCKED`, the response must state that whole-corpus conclusions are incomplete.
## Claim Traceability Gate
For source-backed wiki work, evidence must be traceable at claim granularity.
`raw/official-docs/` and `raw/company-tech-blogs/` documents should expose stable claim IDs in a `Claims Extracted` table:
```text
| Claim ID | Claim | Evidence quote | Strength | Applies to | Does not prove |
|---|---|---|---|---|---|
| C1 | <source-backed claim> | <quote/section> | official-vendor-doc | <condition> | <boundary> |
```
`raw/branch-notes/` documents should map decisions to those claims:
```text
| Decision ID | Decision | Supporting Claims | Evidence Strength | Open Risk |
|---|---|---|---|---|
| D1 | <decision> | raw/official-docs/<slug>.md#C1 | official-vendor-doc | <risk> |
```
Rules:
1. A source claim is only what the source directly says. Project application is not a source claim.
2. A branch decision without at least one supporting claim is `UNSUPPORTED_DECISION`.
3. A company-tech-blog claim is a case study, not a universal rule, unless corroborated by an official source.
4. A wiki concept may summarize only claim-backed knowledge as `FACT`. Anything else must be marked `INFERENCE` or `needs-confirmation`.
5. Audit reports must not say a decision is "officially supported" unless the linked claim strength is `official-standard`, `official-vendor-doc`, or `official-reference`.
## Whole-Corpus Claim Gate
The agent does not summarize, rank, approve, reject, or make recommendations about a whole corpus unless every in-scope file is either:
- `READ_FULL`, or
- `READ_PARTIAL` with the limitation explicitly carried into the conclusion.
If any in-scope file is `NOT_READ` or `BLOCKED`, the agent must say the corpus-level conclusion is incomplete and identify exactly which files remain unreviewed.
## Mandatory Subagent Dispatch
Split work across multiple Read calls (or redirect document-heavy research to LLM Wiki `wiki-research-lane`) when any of these are true:
- More than 10 files must be reviewed.
- More than 5,000 lines must be reviewed.
- The corpus contains 3 or more independent topics.
- The user asks for an exhaustive review.
- The user explicitly asks the agent to use subagents.
- The agent cannot safely keep all evidence in one context window.
Each dispatched subagent must receive:
- the exact file list for its slice,
- the required output contract,
- the requirement to produce an evidence matrix,
- a prohibition on filename-only conclusions,
- instructions to label unread files as `NOT_READ` or `BLOCKED`.
The controller merges only evidence-backed findings. Subagent reports without an evidence matrix are treated as `BLOCKED`.
## Pre-Send Output Gate
Before sending any multi-file response, the agent must run a literal text check against its own draft. The draft is `BLOCKED` and must be rewritten if any of these conditions fails.
1. The draft contains the literal string `| Path | Status | Evidence | Extracted facts |`. No matrix → `BLOCKED`.
2. Row count in the matrix equals the number of in-scope files. Count mismatch → `BLOCKED` unless the draft includes an explicit reconciliation block naming every file that is in scope but absent from the matrix, along with the reason.
3. Every row's Status column is exactly one of `READ_FULL`, `READ_PARTIAL`, `NOT_READ`, `BLOCKED`. Any other value → `BLOCKED`.
4. Every concrete factual claim in the draft (numbers, setting names, literal quotes, behavior assertions) is tied to a row whose Status is `READ_FULL` or `READ_PARTIAL`. A claim tied to a `NOT_READ` or `BLOCKED` row → remove the claim or relabel it `UNVERIFIED` before sending.
5. Any file mentioned in a priority list, "top issues" table, summary table, or recommendation block must also have a row in the evidence matrix with Status `READ_FULL` or `READ_PARTIAL`. Priority references to unread files → `BLOCKED`.
6. The user-stated count of files (if the user said "N files") matches the matrix row count, or the draft contains an explicit reconciliation paragraph naming every file that did not get its own row and why.
If the draft fails this gate, the agent does not send it. It marks the draft `BLOCKED`, identifies the missing rows or unsupported claims, dispatches the necessary subagents or reads, and produces a new draft that passes the gate.
Apology is not evidence. Polished prose is not evidence. Confidence is not evidence. Only `READ_FULL` and `READ_PARTIAL` rows are evidence.
## Failure Handling
If the agent realizes mid-response that it answered from filenames, memory, assumptions, or general expertise:
1. Stop expanding the answer.
2. State exactly which claims were unsupported, using the named labels above.
3. Provide the actual read status for each in-scope file.
4. Re-run the work with subagent dispatch and an evidence matrix before stating any new conclusions.
The agent does not paper over missing evidence with apology, confidence, or polished prose. Apologies are not evidence.
@@ -0,0 +1,80 @@
---
title: Execution Profiles Rule
source_type: meta
status: stable
tags: [meta, llm-wiki, validation, testing, static-analysis]
last_reviewed: 2026-07-20
---
# Execution Profiles Rule
이 rule은 작업 비용을 줄이기 위한 생략 규칙이 아니라, 어떤 검증을 항상 실행하고 어떤 고비용 review를 profile·risk에 따라 추가할지 정하는 실행 계약이다. 기계 판독 SSOT는 [`harness/source/execution-profiles.json`](../harness/source/execution-profiles.json)이다.
## 공통 불변식
모든 profile은 다음 cheap deterministic check를 실행한다. profile이나 risk를 이유로 생략할 수 없다.
- input schema와 repo-relative path 검증
- source 존재 여부, source 전체 bytes의 SHA-256, 지정 line range 검증
- 지정 line range 안 exact UTF-8 quote의 byte 일치 검증
- `(finding.id, finding.role)` 중복 검증
- 기록된 `argv`, `exit_code`, `stdout_utf8`, `stdout_sha256`, `exact_match` 검증
- 기존 frontmatter, link, naming, taxonomy, coverage 같은 적용 대상별 결정론 검사
quote proof의 SSOT는 `harness/runtime/proof_manifest.py`가 PASS로 검증한 `proof-manifest/v1` JSON이다. 이 도구는 manifest의 `argv`를 실행하지 않는다. 캡처한 stdout과 source bytes를 검증할 뿐이며, 기본 실행은 read/verify only다. `--output <path>`가 명시된 경우에만 PASS manifest를 atomic write한다. 불일치, 파일 부재, hash mismatch, line range 오류, non-zero exit, `exact_match=false`, finding-role 중복은 non-zero다.
## Runtime CLI
runtime은 모두 Python stdlib만 사용하며 JSON 결과와 non-zero 실패 코드를 반환한다.
```bash
# project Work Item → branch packet + project MOC (쓰기 전 staging 검증)
python3 harness/runtime/branch_from_project.py <project> <WI-ID> --dry-run
python3 harness/runtime/branch_from_project.py <project> <WI-ID> --apply
# structured project/parent_branch edge → generated children reverse view
python3 harness/runtime/moc_indexer.py --root . --check
python3 harness/runtime/moc_indexer.py --root . --apply
# proof-request/v1의 source + expected quote → fixed proof-manifest/v1
python3 harness/runtime/proof_runner.py <proof-request.json> \
--repo-root . --run-root <run-root> --output <proof-manifest.json>
# persisted proof reference hard gate
python3 harness/runtime/proof_hard_gate.py <proof-manifest.json> \
--repo-root . --run-root <run-root> \
--manifest-sha256 <sha256> \
--proof-count <N> --pass-count <N> --fail-count 0
# 사용자-facing 한국어 Markdown 검사; fix는 명확한 heading mapping만 변경
python3 harness/runtime/korean_lint.py --check <markdown...>
python3 harness/runtime/korean_lint.py --fix-headings <markdown...>
```
`branch_from_project.py`는 target이 이미 있거나 WI/DEC pinned revision이 맞지 않으면 쓰지 않는다. apply의 project/branch 교체 중 한 파일이라도 실패하면 앞선 교체를 원본 bytes로 rollback한다. `proof_runner.py`는 request에서 argv를 받지 않고 `proof-runner/exact-utf8-v1` 고정 실행 기록만 생성한 뒤 같은 프로세스에서 `proof_manifest.py` verifier를 호출한다.
## Profile 선택
| Profile | 용도 | Semantic review | Adversarial review |
|---|---|---|---|
| `capture` | raw 원자료와 외부 source를 빠르게 보존 | `risk >= high`일 때 | 기본 불필요 |
| `design` | 대안 비교, 결정 조건, 구현 계약 작성 | `risk >= medium`일 때 | `risk >= high`일 때 |
| `audit` | corpus/report 감사와 finding 검증 | 항상 필수 | findings 5개 이상 또는 `risk >= high`일 때 필수 |
| `publish` | canonical 기반 외부 파생·공개 전 최종 검수 | 항상 필수 | findings 5개 이상, `risk >= high`, 공개 claim 존재 중 하나면 필수 |
risk 순서는 `low < medium < high < critical`이다. 여러 조건이 맞으면 더 강한 조건을 적용한다. 애매하면 한 단계 높은 risk를 선택하거나 보고서에 미확정 risk를 실패 gate로 남긴다.
## Audit 비약화 조건
`audit` profile은 기존 reporting 계약의 9 gates(`scope`, `matrix`, `finding`, `quote`, `adversarial`, `priority`, `link`, `language`, `artifact`)와 verdict 산식을 그대로 유지한다. proof manifest PASS는 `quote_gate`의 증거 형식만 교체하며 다른 gate를 대신하지 않는다. risk-sampled adversarial review는 기존과 같이 `PARTIAL (risk-sampled)`이고 `COMPLETE` 근거가 될 수 없다.
## Report 표현 v2
신규 v2 보고서는 모든 성공 proof를 Markdown에 복제하지 않는다.
- §7.1에는 manifest 경로, `run.id`, profile, proof count, manifest SHA-256, verifier exit code를 기록한다.
- Markdown에는 실패 proof만 `finding.id/role`, error code, source path와 line range 단위로 펼친다. 원문 stdout 전체를 성공 행마다 붙이지 않는다.
- controller는 manifest를 다시 검증한 실제 명령과 exit code를 `controller-verification.md`에 남긴다.
- manifest가 없거나 verifier가 non-zero면 `quote_gate` FAIL이다.
과거 audit 산출물은 재작성하지 않는다. 신규 run의 quote gate는 `proof-manifest/v1``proof-hard-gate-result/v1`만 사용하며 inline shell transcript나 `sed-proofs.md`를 대체 SSOT로 인정하지 않는다.
@@ -0,0 +1,41 @@
# rules/extraction-tiering — Tiered Extraction 계약 (싼 발췌 + 검증 게이트)
> `rules/` 의 방법론 규칙. multi-doc 작업에서 토큰 대부분은 **발췌(다파일 정독 input)** 가 먹는다 — 그런데 발췌 품질은 발췌자의 지능이 아니라 **검증 게이트(결정론 quote-verifier)** 가 보장한다. 따라서 발췌는 가장 싼 엔진에 위임할 수 있고, 비싼 모델(opus)은 *판단* 에만 쓴다.
> 집행 도구: `scripts/deep-research/deep_research/extract.py` (발췌 브로커 드라이버) · `deep_research/vote.py` (cross-vendor 적대 표) · `.claude/hooks/wiki_consistency_check.py --packets` (T0 팩킷) · `.claude/agents/extraction-broker.md` (T2 브로커 agent).
## 4-Tier 표
| Tier | 엔진 | 담당 | 비용 |
|---|---|---|---|
| **T0** | 결정론 (Python) | 린터·검사기·팩킷 빌더 (`wiki_structure_lint.py` · `wiki_consistency_check.py --packets` · quote-verifier) | 0 토큰 |
| **T1** | 외부 구독 CLI | **codex = 구조화 발췌** (`--output-schema` JSON 강제) · **agy = web 조사·요약**. quorum 표결은 **양쪽 1표씩** (cross-vendor 독립 실패 모드) | 별도 구독 |
| **T2** | haiku | 브로커·글루 — `extraction-broker`(드라이버 구동 + 실패분 재발췌) · `wiki-link-verifier` | 저 |
| **T3** | sonnet | **레포 쓰기 에이전트**`wiki-doc-author` · `wiki-source-summarizer`. 쓰기는 반드시 Claude 훅(claim gate / structure lint) 경유 | 중 |
| **T4** | opus | **판단** — 웹조사 방향 결정·작업 지시·모순 판결(`wiki-consistency-auditor`)·판정 3종(`branch-depth-auditor`/`coverage-auditor`/`project-readiness-auditor`) | 고 |
## 5계명 (Hard Rules)
| # | 계명 | 내용 |
|---|---|---|
| **1** | **외부 CLI = read-only 추출기** | 드라이버(`extract.py`/`vote.py`)가 파일 내용을 줄번호 붙여 프롬프트에 내장 — 외부 엔진은 repo 에 접근하지 않는다. **레포 쓰기는 Claude 훅 경유만** (codex/agy 직접 쓰기 금지). |
| **2** | **무검증 발췌 소비 금지** | 외부 발췌의 모든 verbatim 인용은 quote-verifier(결정론 re-grep)를 거친다 — PASS/CORRECTED 통과분만 상위 티어로 올라간다. DROPPED(원문 부재 = 위조·의역)는 폐기. |
| **3** | **engine funnel 필수** | 어떤 엔진이 몇 파일을 처리/실패했는지 항상 기록 — **no silent engine swap**. digest 의 `**Engines:**` 행 + ```wiki-stats``` 블록이 증거. |
| **4** | **opus 컨텍스트에 raw corpus 반입 금지** | opus 는 digest + `file:line` 포인터만 받는다. 판결이 모호한 지점만 해당 라인을 직접 Read (포인터 추적 — 전문 정독 아님). |
| **5** | **fallback 사다리 codex→agy→haiku→sonnet** | 각 단계 실패 시 다음 단계로 — 단계마다 funnel 에 기록. 사다리를 건너뛰거나 기록 없이 갈아타지 않는다. |
## 사용법 표 (작업별 1순위 / 검증 / fallback)
| 작업 | 1순위 | 검증 | fallback |
|---|---|---|---|
| bulk 파일 발췌 (다수 raw 정독 input) | `extraction-broker` → `cd scripts/deep-research && python3 -m deep_research.extract --backend codex ...` (구조화=codex 우선, web성 질문=`--backend antigravity`) | quote-verifier 내장 (PASS/CORRECTED/DROPPED) | 실패 파일은 broker(haiku) 직접 재발췌 → 그래도 실패면 sonnet lane |
| quorum 적대 표결 (lint CRITICAL≥5 등) | `wiki-adversarial-reviewer`(Claude) 1표 + `python3 -m deep_research.vote --backend codex` 1표 + `--backend antigravity` 1표 | `wiki_quorum.py` 결정론 합산 (≥2 REJECT=KILL) | 외부 표 실패 시 해당 표만 Claude 추가 dispatch 로 대체 + funnel 기록 |
| /sync 의미 대조 input | `python3 .claude/hooks/wiki_consistency_check.py --packets [slug]` (T0, 0토큰) | 결정론 추출이므로 검증 불요 | 팩킷 모호 시 auditor 가 해당 원문 라인만 Read |
| 합성·추출 권고 (synthesis) | `wiki-research-lane` — **검증된 digest 를 1차 input 으로 소비** (직접 전수 정독은 broker 불가 시 fallback) | digest 인용은 이미 verifier 통과분 | broker 불가 시 기존 직접 정독 모드 |
| 레포 쓰기 (raw/wiki 문서) | `wiki-doc-author` · `wiki-source-summarizer` (T3 sonnet, 훅 경유) | claim gate + structure lint (PreToolUse/PostToolUse) | — (외부 엔진으로 대체 금지 — 계명 1) |
| 링크·구조 감사 | `wiki-link-verifier` (T2 haiku) + `wiki_structure_lint.py` (T0) | self-grep 카운트 일치 | — |
| 판결·게이트 (모순/깊이/완전성/readiness) | T4 opus 판정 agent 4종 | wiki-verdict 스키마 훅 검증 | 하향 금지 — 판단은 싼 티어로 내리지 않는다 |
## 한계
- **외부 모델 coverage 누락 리스크** — codex/agy 가 관련 라인을 못 찾으면 digest 에 *없는 것* 은 검증 게이트가 못 잡는다 (verifier 는 위조를 잡지, 누락은 못 잡음). 완화: funnel 균형 감시(파일별 인용 0건은 의심) + 핵심 작업은 **cross-vendor 2-pass** (codex·agy 양쪽 발췌 후 합집합).
- **구독 율제한** — 외부 CLI 는 rate limit 이 있다. fan-out 은 bounded (`extract.py` CONCURRENCY=3) — 무한 병렬 금지, 대량 작업은 배치 분할.
+241
View File
@@ -0,0 +1,241 @@
---
title: LLM Wiki Linking Rules
source_type: meta
status: stable
tags: [meta, linking-rules]
last_reviewed: 2026-05-25
---
# LLM Wiki Linking Rules
본 문서는 **모든 raw / wiki 문서가 따라야 하는 연결 규칙**을 정의한다. 템플릿(`templates/*.md`)이 이 규칙을 강제하도록 설계되어 있고, 본 문서는 그 규칙의 single source of truth.
> Layer: `templates/` — 메타 규약. 본 문서는 다른 문서를 만들 때 참고하는 정책.
## 1. 핵심 원칙 — Project as the Sole Root
> **모든 raw 문서는 예외 없이 branch 또는 project로 upward link 의무.** "자기 충족" 문서 없음.
```
raw/project-notes/<project> ← 유일한 entry point (root)
raw/branch-notes/<branch> ← project의 직접 자식 (모든 branch)
│ (선택, 하위 작업 있을 때만)
raw/branch-notes/<sub-branch> ← 부모 branch 있는 경우
│ (선택)
raw/branch-notes/<sub-sub-branch> ← 더 깊은 자식
Leaves (branch에 매달림): Sources (branch에서 인용 + branch로 upward 연결):
- raw/errors/<incident> - raw/official-docs/<x>
- raw/interviews/<question> - raw/company-tech-blogs/<x>
- raw/lectures/<lecture>
- raw/job-postings/<posting>
- raw/blog-topics/<topic>
```
**중요**: "root branch" 라는 별도 개념은 **없다**. 모든 branch 는 동등한 `raw/branch-notes/` 1차 시민이며, `parent_branch` 필드가 비어있느냐 (= project 직접 자식) 채워져 있느냐 (= 다른 branch 의 자식) 로 위치가 결정된다. `raw/project-notes/<project>` 가 유일한 cluster root.
자료(공식 문서·기업 블로그·강의)도 **혼자 존재하지 않는다.** 어느 branch 의 구현 결정 근거로서 보관됨. 따라서 자료도 branch 또는 project로 upward link 의무.
## 2. Mandatory Upward Link 표
각 문서가 만들어질 때 **최소한 만족해야 하는 link 의무**.
| 문서 종류 | Mandatory Upward Link | Mandatory 추가 |
|---|---|---|
| `raw/project-notes/<p>` | (root — upward 면제) | — |
| `raw/branch-notes/<b>` — project 직접 자식 (`parent_branch:` 비어있음) | `[[raw/project-notes/<project>]]` | Sources 1개+ (단순 셋업·실험 0개 허용, §5) |
| `raw/branch-notes/<b>` — 다른 branch 의 자식 (`parent_branch:` 채워짐) | `[[raw/branch-notes/<parent-branch>]]` (`parent_branch` frontmatter 와 일치) | Sources 1개+ |
| `raw/errors/<e>` | `[[raw/branch-notes/<관련 branch>]]` 또는 `[[raw/project-notes/<p>]]` | 해결 근거 1개+ |
| `raw/interviews/<q>` | `[[raw/branch-notes/<관련 branch>]]` 또는 `[[raw/project-notes/<p>]]` | — |
| `raw/lectures/<l>` | `[[raw/branch-notes/<학습 동기 branch>]]` 또는 `[[raw/project-notes/<p>]]` | — |
| `raw/job-postings/<p>` | `[[raw/branch-notes/<관련 branch>]]` 또는 `[[raw/project-notes/<p>]]` | — |
| `raw/blog-topics/<t>` | `[[raw/branch-notes/<관련 branch>]]` 또는 `[[raw/project-notes/<p>]]` | canonical 전환 후보 명시 |
| `raw/daily-notes/<date>` | 그날 작업한 branch-notes 전부 (양방향 nav) | — |
| `raw/official-docs/<x>` | `[[raw/branch-notes/<...>]]` 1개+ 또는 `[[raw/project-notes/<p>]]` (foundational 조사 시) | URL 필수 |
| `raw/company-tech-blogs/<x>` | 동일 — branch 또는 project | URL 필수 |
| `wiki/projects/<project-slug>/<topic>.md` (nested, §11) | `[[raw/project-notes/<project-slug>]]` + `[[raw/branch-notes/<...>]]` 1개+ | `wiki/concepts/` 1개+ |
| `wiki/concepts/<c>` | (canonical, no upward) | `[[raw/official-docs/...]]` 또는 `[[raw/company-tech-blogs/...]]` 1개+ + 관련 `wiki/projects/` (Project Application) |
| `wiki/interview/<q>` | `wiki/concepts/` 또는 `wiki/projects/` 1개+ | — |
| `wiki/portfolio/<t>` | `wiki/projects/` 필수 | — |
| `wiki/blog/<post>` | `wiki/concepts/` 또는 `wiki/projects/` 1개+ | — |
`wiki/concepts/` 만 upward 의무에서 제외됨 — canonical 일반 개념은 특정 프로젝트에 종속되지 않을 수 있음. 단 `## Project Application` 섹션에서 적용된 wiki/projects를 가리키는 것은 권장.
## 3. 다중 부모 / Multi-parent
같은 자료가 여러 branch에서 인용될 수 있음. 이 경우:
1. `frontmatter``related_branches:` 에 모든 branch 이름 나열
2. 본문에 `## Parent / 활용 branch` 표를 두고 각 branch + "이 자료가 정당화하는 결정" 한 줄로 기록
예: `raw/official-docs/keycloak-oidc-rfc.md`
```yaml
---
related_branches: [feature-keycloak-oauth2-proxy-oidc-flow, feature-keycloak-nginx-auth-request-integration]
related_projects: [keycloak-patterns]
---
```
```markdown
## Parent / 활용 branch
| Branch | 이 자료가 정당화하는 결정 |
|---|---|
| [[raw/branch-notes/feature-keycloak-oauth2-proxy-oidc-flow]] | provider=keycloak-oidc 설정의 RFC 근거 |
| [[raw/branch-notes/feature-keycloak-nginx-auth-request-integration]] | nginx auth_request 통합의 OIDC handshake 흐름 근거 |
```
## 4. Parent canonical + generated Cluster reverse view
v2 graph contract에서 child의 `project` / `parent_branch` frontmatter와 `## Branch Contract Packet`이 **canonical Parent edge**다. Hub의 Cluster는 이 edge에서 생성된 reverse view이며, 새 v2 문서에서 수기로 자식 소유권을 선언하지 않는다. Work Item의 decision/dependency edge는 `DEC-...@revision` / `WI-...` pinned ref로 기록한다.
Hub의 자식 목록은 다음 marker **사이만** 생성·교체한다. 검사기도 이 블록만 reverse view로 대조한다.
```markdown
<!-- GENERATED: children:start -->
- [[raw/branch-notes/<child>]]
<!-- GENERATED: children:end -->
```
기존 문서의 수기 `## Cluster`는 legacy 내비게이션으로 보존하되, v2로 승급할 때 marker 블록으로 이관한다. marker/table이 없는 legacy 문서는 strict graph failure가 아니라 `LEGACY_GRAPH_CONTRACT` migration warning + skip으로 처리한다.
Legacy 표현 예시:
각 hub 문서 (`raw/project-notes/`, 자식 branch 를 가진 모든 branch) 는 본문에 `## Cluster / 묶음` 섹션을 두고 자식들을 카테고리별로 명시:
```markdown
## Cluster / 묶음
### Sub-branches (세부 작업)
- [[raw/branch-notes/<sub-1>]] — <한 줄 요약>
### Sources / 근거 자료
- [[raw/official-docs/<...>]]
- [[raw/company-tech-blogs/<...>]]
### Errors (이 branch 작업 중 발생)
- [[raw/errors/<...>]]
### Interview prep (이 작업에서 나올 면접 질문)
- [[raw/interviews/<...>]]
### Lectures (이 작업을 위해 학습)
- [[raw/lectures/<...>]]
### Blog topics / job-posting tie-ins (이 작업에서 글감)
- [[raw/blog-topics/<...>]]
- [[raw/job-postings/<...>]]
- [[wiki/blog/<...>]] (derived 시)
```
→ Obsidian 그래프뷰에서 branch가 자기 cluster의 entry point로 시각화됨. v2에서는 위 목록을 generated marker 블록 안에만 둔다.
## 5. Sources 섹션 강제 — branch 는 근거 없이 만들지 않는다
`raw/branch-notes/<b>` (모든 branch) 는 **최소 1개의 외부 근거**(`[[raw/official-docs/...]]` 또는 `[[raw/company-tech-blogs/...]]` 또는 `[[raw/lectures/...]]`)를 `## Sources / 근거` 표에 명시해야 한다.
근거 자료가 raw 에 아직 없다면 **branch-note 작성 전에** `raw-source-template` (공식·기업 블로그) 또는 `lecture-note-template` (강의) 로 raw 에 등록 후 link.
### prefix 별 Sources 강도
| Prefix | Sources 강도 |
|---|---|
| `feature-` | **필수, 최소 1개+** (이상적으로 공식 문서 1 + 기술 블로그 1, 그리고 검토한 대안의 자료 포함) |
| `fix-` | **필수, 최소 1개+** (재현/원인 분석의 근거) |
| `chore-` | **권장**, 0개 허용. 0개일 경우 본문에 "외부 근거 불필요 이유" 한 줄 (예: "로컬 docker-compose 셋업, 표준 절차") |
| `experiment-` | **권장**, 0개 허용. 동일하게 본문에 사유 한 줄 |
## 6. Daily-note 의 역할
`raw/daily-notes/<date>`**시간축 hub**. 공간축 hub(project/branch)와 직교한다.
- 매일 작성한 daily-note는 그날 작업한 모든 branch-notes를 명시
- branch-note도 작업한 날짜의 daily-notes를 `## 관련 일일 노트` 섹션에 양방향으로 명시
- daily-note에서 파생된 에러·인터뷰·면접·강의 노트는 해당 branch에 매달리되, daily-note 본문에도 짧게 인덱스 가능 (선택)
## 7. Derived layer (wiki/interview · wiki/portfolio · wiki/blog) 파생 룰
CLAUDE.md §15 강제. 다음 규칙은 그 강제의 짧은 요약:
- `wiki/interview/<q>`**canonical (`wiki/concepts/` 또는 `wiki/projects/`)** 에서만 파생. raw에서 직접 파생 금지.
- `wiki/portfolio/<t>``wiki/projects/` 에서만 파생.
- `wiki/blog/<post>``wiki/concepts/` 또는 `wiki/projects/` 에서만 파생.
영감의 출처(예: `raw/blog-topics/`, `raw/job-postings/`, `raw/interviews/`)는 derived 문서의 본문에 link 가능하지만, **사실 근거(Sources)는 canonical에서만 가져옴**.
## 8. 검증 체크리스트 (수동 운영, 자동화는 유보)
다음 항목은 작성자가 직접 체크. 자동화(`/lint`)는 후속 라운드에 결정.
문서 작성 직후 — 작성자 self-check:
- [ ] frontmatter `related_branches` 또는 `related_projects` 가 채워졌는가
- [ ] 본문에 `## Parent` 또는 그에 준하는 upward link 섹션이 있는가
- [ ] branch-note라면 `## Sources / 근거` 가 최소 1개의 외부 자료 link를 포함하는가
- [ ] hub 역할 문서 (`raw/project-notes/` 또는 자식 branch 를 가진 branch) 라면 `## Cluster / 묶음` 섹션이 카테고리별로 채워졌는가
- [ ] derived 문서(`wiki/interview` · `wiki/portfolio` · `wiki/blog`)는 canonical(`wiki/concepts` / `wiki/projects`) link 1개+ 가 있는가
- [ ] Obsidian 그래프뷰에서 이 문서가 cluster에 시각적으로 연결되어 보이는가
> **결정론 집행기**: 위 옵시디언 링크 문법(broken target / dangling anchor / backtick 래핑)은 `.claude/hooks/wiki_structure_lint.py`의 C2 검사가 기계적으로 강제한다 (`--all --links-only`로 vault 전수, zero-tolerance).
> basename 후보가 2개 이상인 non-full-path link는 `AMBIGUOUS_WIKILINK`다. v2 graph는 `.claude/hooks/wiki_graph_contract_check.py`가 `MISSING_PROJECT_BINDING`, `MISSING_INHERITED_DECISION`, `STALE_INHERITANCE_REVISION`, `CONFLICTS_WITH_PROJECT_DECISION`, `UNDECLARED_OVERRIDE`, `MISSING_EXPECTED_EDGE`, `DUPLICATE_DECISION_OWNER`를 검출하며, 공개 `wiki_consistency_check.py --all` 출력에 병합된다. `MISSING_EXPECTED_EDGE`는 batch/post-sync에서만 판정하여 단일 파일 pre-write 생성 순환을 차단하지 않는다.
## 9. Obsidian 그래프 활용 지침
- **Tags**: frontmatter `tags:` 는 카테고리 분류 + Obsidian Tag pane 활용. 핵심 5~7개 이내 권장.
- **Local graph**: 각 문서에서 Local graph view로 직접 연결된 1차/2차 노드만 확인하면 cluster의 entry point 역할 검증 가능.
- **Global graph**: 프로젝트별로 hub-spoke 패턴이 시각적으로 보여야 정상. 한 자료가 그래프상 고립된 점으로 보이면 upward link 누락 신호.
## 10. 어긋난 자료의 처리 / Drift handling
- 어떤 raw 문서가 branch나 project로 연결되지 않은 상태로 발견되면 → 즉시 upward link 추가 또는 (가치 없으면) 보관 폴더 별도 이동
- branch가 사라지거나 머지된 후에도 해당 branch에 연결된 자료는 raw에 영구 보관 — branch-note 자체는 `status_label: merged` 또는 `abandoned` 로 표시되어 보존됨
- 실제 작업·근거가 없는 미치환 scaffold는 삭제하지 않고 `raw/archive/<원래-category>/`로 이동한다. frontmatter에 `status_label: abandoned``archive_reason:`을 남기며, `raw/archive/`는 active graph의 upward link·Cluster 생성 대상에서 제외한다.
- `wiki/concepts/` 처럼 upward 면제 문서가 너무 많은 raw를 끌어안고 있다면, 해당 wiki/concepts/ 와 가까운 wiki/projects/ 를 새로 만들어 cluster 분리
## 11. 카테고리별 템플릿 매핑
| 카테고리 | 필수 템플릿 |
|---|---|
| `raw/project-notes/` | `project-template.md` (구조화 + 아키텍처 hub) — **아키텍처 다이어그램 (`.drawio.svg`) + 시퀀스 다이어그램 (Mermaid) 필수** |
| `raw/diagrams/<project-slug>/` | **draw.io** XML 파일 저장 경로 (프로젝트 단위, 아키텍처 전용). 명명: `architecture-{viewpoint}-YYYY-MM-DD.drawio` 또는 `.drawio.svg` |
| `raw/diagrams/<project-slug>/archived/` | 폐기된 다이어그램 보관 (삭제 대신 이동) |
### Diagram-tool 분리 (엄격)
- **아키텍처 / 컴포넌트 구성도 / 배포 / 데이터 흐름** → **draw.io XML** (`raw/diagrams/` 별도 파일)
- **시퀀스** → **Mermaid `sequenceDiagram`** (본문 inline code block, 별도 파일 X)
- **ER (선택)** → **Mermaid `erDiagram`** (본문 inline)
- 시스템 아키텍처를 Mermaid `graph TD/LR` 로 작성 **금지** — 도구 일관성을 위해 draw.io 강제.
### Diagram 컨퍼런스급 표준 (필수)
다이어그램 작성 시 [[rules/diagram-standards]] 정독 — Toss SLASH / Kakao if(dev) / Naver DEVIEW 수준의 컨퍼런스급 다이어그램 기준. self-check 모두 만족해야 발표 가능 수준.
## 12. Hub / MOC 명명 컨벤션
- **Named hub 패턴 (Obsidian-native)**: 모든 hub/MOC 파일은 **의미 있는 고유 이름**을 사용. `index.md` / `_index.md` (Hugo·Jekyll 등 static-site 컨벤션) 사용 **금지** — wikilink 가 `[[index]]` 처럼 의미 없는 노드로 보이고 Graph view 라벨이 무력화됨.
- **계층별 위치**:
- `wiki/llm-wiki.md` — 전체 vault 의 Map of Content (MOC). 진입점.
- `wiki/projects/<project-slug>.md` — 해당 project 의 wiki 하위 hub. 옆에 `wiki/projects/<project-slug>/` 폴더가 존재할 때 그 폴더 안 sub-doc 들의 MOC 역할 (folder-note 패턴).
- 다른 sub-directory hub 가 필요하면 동일 패턴 (`<dir-slug>.md` + `<dir-slug>/` 폴더 sibling).
- **wikilink 표기**: hub 파일명이 vault 내에서 고유하므로 basename 만으로 참조 가능 — `[[ca-tmpl]]`, `[[llm-wiki]]`. 다른 디렉토리에 동명 파일이 생긴다면 그 때 full path 로 disambiguate.
- **Folder-note 시각화**: Obsidian Folder Notes 플러그인 설치 시 sibling `<slug>.md``<slug>/` 폴더의 "표지" 역할로 보임. 플러그인 없이도 wikilink + Graph 동작은 동일.
| `raw/branch-notes/` | `branch-note-template.md` |
| `raw/daily-notes/` | `daily-note-template.md` |
| `raw/errors/` | `error-note-template.md` |
| `raw/interviews/` | `interview-prep-template.md` |
| `raw/job-postings/` | `job-posting-template.md` |
| `raw/blog-topics/` | `blog-topic-template.md` |
| `raw/lectures/` | `lecture-note-template.md` |
| `raw/official-docs/` | `raw-source-template.md` (source_type=official-doc) |
| `raw/company-tech-blogs/` | `raw-source-template.md` (source_type=company-tech-blog) |
| `wiki/concepts/` | `concept-template.md` 또는 `source-summary-template.md` |
| `wiki/projects/<project-slug>/<topic>.md` (nested) | `wiki-project-template.md` — sibling `wiki/projects/<project-slug>.md` (named MOC) 와 1:N |
| `wiki/interview/` | `interview-template.md` |
| `wiki/portfolio/` | `portfolio-template.md` |
| `wiki/blog/` | `blog-template.md` |
+280
View File
@@ -0,0 +1,280 @@
---
title: LLM Wiki Naming Conventions
source_type: meta
status: stable
tags: [meta, naming-conventions]
last_reviewed: 2026-05-25
---
# LLM Wiki Naming Conventions
본 문서는 **파일·디렉터리·식별자의 명명 규칙**을 정의한다. 일관성 없는 명명은 검색·정렬·그래프뷰에서 노이즈가 된다.
> Layer: `templates/` — 메타 규약. 모든 raw/wiki 문서 작성 시 본 규칙 준수.
## 1. 공통 원칙
- **모두 영문 kebab-case** (예: `feature-architecture-enforcement-rules`, NOT `featureArchitectureEnforcementRules`, NOT `feature_architecture_enforcement_rules`)
- **한글 파일명 금지** — Obsidian 검색·터미널 호환·정렬 문제
- **공백 금지** — kebab 으로 대체
- **숫자 prefix 금지** (날짜 외) — 예: `01-intro.md` 같은 정렬용 prefix 안 쓴다. 정렬은 frontmatter `created:` 또는 카테고리로
- **확장자**: `.md` 통일 (Obsidian 표준). drawio 파일은 `.drawio.svg`
## 2. 카테고리별 명명 규칙
### 2.1 `raw/branch-notes/<branch-name>.md`
**컨벤션 결정: `<branch-prefix>-<content-descriptor>` 단일 형식 통일. 슬러그는 _구현 내용을 표현_ 해야 한다.**
#### 2.1.1 Prefix (필수, 4종)
`branch-prefix` 는 다음 **4종 중 정확히 하나** 사용. `develop-`**제거됨** — 기능 구현 작업은 규모 무관 `feature-` 사용.
| Prefix | 용도 | 예시 |
|---|---|---|
| **`feature-`** (default) | **모든 기능 구현 작업.** 단일 기능이든 sub-branch 여러 개 가지는 큰 기능이든 동일하게 `feature-`. 일반적으로 PR 한 묶음에 머지될 단위. | `feature-keycloak-oidc-integration`, `feature-domain-event-outbox-contract`, `feature-keycloak-oauth2-proxy-oidc-flow` |
| `fix-` | 단일 버그 수정 작업 | `fix-auth-token-leak`, `fix-jwt-iss-claim-mismatch` |
| `chore-` | 인프라·문서·도구 변경 (코드 동작 변경 없음). 환경 셋업·라이브러리 업그레이드·CI 설정 등 | `chore-update-archunit-rules`, `chore-local-postgres-docker-compose` |
| `experiment-` | 검증 목적 실험. 머지 안 할 수도 있고 결과만 기록. | `experiment-tail-based-sampling`, `experiment-redis-vs-caffeine-cache` |
**왜 `develop-` 제거**: 이전엔 "큰 작업 묶음"용으로 `develop-`, "단일 기능"용으로 `feature-` 였지만, 실제 git 브랜치 워크플로우에서는 큰 작업도 `feature/`로 시작한다. "큰지 작은지" 판단을 prefix 결정 시점에 강요하는 것은 자연스럽지 않다. → `feature-`로 통합. 작업 규모는 `parent_branch:` 와 sub-branch 분할로 표현.
**기존 `develop-*` 슬러그 처리**: `wiki-doc-author` mode=migrate 로 점진적 rename 권고. 자동 `mv` 안 함 — wikilink 영향 검토 필요.
#### 2.1.2 Content descriptor — _구현 내용 기반 명명 (HARD RULE)_
슬러그의 prefix 뒤 부분은 **그 branch 가 무엇을 구현/문서화하는지** 를 4~8 단어 영문 kebab-case 로 명확히 표현한다.
**좋은 예** (파일명만 보고 작업 내용 파악 가능):
- `feature-keycloak-oauth2-proxy-oidc-flow` ← oauth2-proxy 의 OIDC 흐름 구현
- `feature-keycloak-nginx-auth-request-integration` ← nginx auth_request 모듈 통합
- `feature-keycloak-header-spoofing-defense` ← X-Forwarded-User 헤더 spoofing 방어
- `fix-keycloak-hostname-claim-mismatch` ← KC_HOSTNAME 미설정 시 JWT iss claim mismatch 버그
- `feature-keycloak-edge-forwardauth-no-google` ← P1A 패턴 전체
- `feature-domain-event-outbox-contract` ← outbox 패턴 + transactional event publish 계약
**나쁜 예 (금지)**:
-`feature-project-alpha-1` — numbered hierarchy. 슬러그에서 작업 내용을 알 수 없음
-`feature-project-alpha-1-2` — 2단 numbered hierarchy. 파일 listing 에서 의미 추출 불가능
-`feature-foo-bar-2` — 동일 문제 (의미 없는 numeric suffix)
-`develop-anything``develop-` 자체가 제거된 prefix (위 §2.1.1 참조)
-`feature-1-2-3` — 의미 zero
#### 2.1.3 Hierarchy 표기 — _슬러그가 아니라 frontmatter 로_
계층은 **슬러그에 인코딩하지 않는다**. "root branch" 라는 별도 개념도 없다 — 모든 branch 는 동등하고, 위치는 `parent_branch:` 필드로만 표현된다. 다음 두 곳에서만 표현:
1. **frontmatter `parent_branch:`** — 직계 부모 branch slug. **project 의 직접 자식 branch 는 이 필드를 비워두고 `related_projects:` 만 채운다.** 다른 branch 의 자식이면 부모 branch slug 명시.
2. **`## Parent / 부모 (필수)` 섹션** — 부모 wikilink (project 또는 parent branch) + 형제 wikilink + (선택) 조부모.
이렇게 하면 파일 시스템 listing 만 보고 "이게 무슨 작업인지" 즉시 알 수 있고, 계층 정보는 graph view / backlink / 본문 섹션에서 자연스럽게 드러난다.
#### 2.1.4 동일 패턴 그룹 묶기 — prefix 접두어 활용
같은 큰 주제(예: keycloak 6 패턴) 의 sub-branch 들이 파일 정렬 시 인접하게 보이도록 **공통 접두어** 를 사용하는 것은 허용 (numbered hierarchy 아니라 content prefix 이므로):
- `feature-keycloak-edge-forwardauth-no-google`
- `feature-keycloak-edge-forwardauth-google-federation`
- `feature-keycloak-cluster-internal-no-google`
- ...
- `feature-keycloak-oauth2-proxy-oidc-flow`
- `feature-keycloak-nginx-auth-request-integration`
위처럼 `feature-keycloak-` 접두어가 동일 프로젝트 sub-branch 들을 자연 정렬하면서도, 슬러그 후반부가 각자 구현 내용을 표현한다.
#### 2.1.5 기타 금지 패턴
-`feature/blabla` (슬래시 — 파일명 호환 문제)
-`develop_keycloak_patterns` (snake_case)
-`01-keycloak-patterns` (숫자 정렬 prefix)
-`keycloak-patterns` (prefix 누락)
-`feature-project-alpha-1` (numbered hierarchy — §2.1.2 위반)
-`develop-*` 어떤 슬러그든 (`develop-` prefix 자체 제거됨 — §2.1.1)
#### 2.1.6 Self-check (작성·rename 시 적용)
- [ ] prefix 가 §2.1.1 표의 4종 (`feature-` / `fix-` / `chore-` / `experiment-`) 중 정확히 1개
- [ ] **prefix 뒤 슬러그가 구현 내용을 4~8 단어로 표현 (§2.1.2)**
- [ ] **숫자 hierarchy(`-1`, `-1-1` 등) 슬러그 후반부에 없음 (§2.1.3)**
- [ ] 계층 정보가 frontmatter `parent_branch:``## Parent` 섹션에 있음
- [ ] 영문 kebab-case · 공백·언더스코어·CamelCase 없음
- [ ] 같은 큰 주제 sub-branch 들이 공통 content prefix 로 자연 정렬
위 self-check 미통과 슬러그 = 작성·rename 거부.
### 2.2 `raw/daily-notes/<YYYY-MM-DD>.md`
- 형식: ISO-8601 날짜 그대로 (예: `2026-05-25.md`)
- 다른 prefix·suffix 금지
### 2.2.1 `raw/daily-tasks/<track>/<YYYY-MM-DD>-<implementation-slug>.md`
- 형식: `YYYY-MM-DD-<implementation-slug>.md`
- `<track>``{develop, infra}` (폴더로만 표현 — 슬러그 자체에는 track prefix 넣지 않는다. 파일 경로가 이미 track 을 명시)
- `YYYY-MM-DD` = frontmatter `target_date` 와 동일 (수행 예정일). `created` 와 다를 수 있음 — 미래 과제 미리 작성 시.
- `<implementation-slug>`: **무엇을 배우고 구현하는지** 를 4~7 단어 영문 kebab-case 로 표현. 슬러그만 보고도 학습 내용 파악 가능해야 함.
**좋은 예**:
- `raw/daily-tasks/develop/2026-05-29-archunit-controller-domain-return-rule.md`
- `raw/daily-tasks/develop/2026-05-30-jackson-fail-on-unknown-properties-policy.md`
- `raw/daily-tasks/infra/2026-05-29-actuator-readiness-probe-db-disconnect.md`
- `raw/daily-tasks/infra/2026-05-30-prometheus-pod-restart-alert-rule.md`
**나쁜 예 (금지)**:
-`develop/task-1.md` (의미 zero — numbered placeholder)
-`develop/2026-05-29-task.md` (slug 가 의미 zero)
-`infra/2026-05-29-day-3-monitoring.md` (day-N hierarchy)
-`develop/2026-05-29-오늘과제.md` (한글)
-`develop/develop-2026-05-29-archunit-rule.md` (track 이 경로와 중복)
**Self-check**:
- [ ] 경로가 `raw/daily-tasks/develop/` 또는 `raw/daily-tasks/infra/` 둘 중 하나
- [ ] 파일명이 `YYYY-MM-DD-` 로 시작 (날짜 정렬 가능)
- [ ] 날짜 뒤 슬러그가 학습 내용 4~7 단어로 명시
- [ ] frontmatter `track` 이 폴더와 일치
- [ ] `parent_project` 또는 `parent_branch` 중 최소 하나 채워짐
### 2.3 `raw/errors/<short-error-slug>.md`
- 형식: `<문제-짧은-키워드>-<YYYY-MM-DD>.md` (날짜 suffix 권장 — 같은 에러 재발 가능성)
- 예: `oidc-discovery-failure-2026-05-25.md`, `hikari-pool-exhausted-2026-05-26.md`
- 짧고 검색 가능한 슬러그 (4~6 단어 이내)
### 2.4 `raw/interviews/<question-slug>.md`
- 형식: `<주제-키워드>.md` (날짜 없음 — 영구 자료)
- 예: `clean-architecture-vs-hexagonal.md`, `idempotency-key-distributed-lock.md`
- 질문 원문이 길어도 슬러그는 4~7 단어 이내로
### 2.5 `raw/job-postings/<company>-<role-slug>.md`
- 형식: `<회사슬러그>-<역할슬러그>-<YYYY-MM-DD>.md`
- 회사 슬러그: 영문 (예: `toss`, `kakao`, `naver`, `coupang`)
- 예: `toss-backend-senior-2026-05-25.md`
- 한국 회사는 영문 음역 권장 (검색 일관성)
### 2.5.1 `raw/blog-topics/<topic-slug>-<YYYY-MM-DD>.md`
- 형식: `<글감-주제-슬러그>-<YYYY-MM-DD>.md`
- 예: `clean-architecture-boundary-enforcement-2026-05-28.md`
- 채용공고에서 나온 글감은 `raw/job-postings/`에 두고, 일반 작업·학습·트러블슈팅에서 나온 글감만 여기에 둔다.
- `wiki/blog/` 파일명을 미리 wikilink로 만들지 않는다. 아직 생성되지 않은 derived 파일은 일반 경로 텍스트로만 후보 표기한다.
### 2.6 `raw/lectures/<course-slug>-<topic-or-episode>.md`
- 형식: `<코스슬러그>-<주제 또는 에피소드 번호>.md`
- 예: `udemy-spring-security-jwt-rotation.md`, `kafka-summit-2024-exactly-once.md`
- 강의가 시리즈면 `-ep01`, `-ep02` 또는 핵심 토픽 슬러그
### 2.7 `raw/official-docs/<doc-slug>-<vendor>.md`
- 형식: `<주제 슬러그>-<벤더 슬러그>.md`
- 예: `actuator-endpoint-exposure-spring-official.md`, `oidc-discovery-keycloak-official.md`
- 벤더 슬러그 끝에 `-official` 또는 `-rfc` 같은 명시적 suffix 권장 (output type 식별)
- 같은 주제의 여러 공식 자료가 있으면 `-v1`, `-v2` 또는 발행연도 suffix
### 2.8 `raw/company-tech-blogs/<topic>-<company>.md`
- 형식: `<주제 슬러그>-<회사슬러그>.md`
- 예: `api-versioning-stripe-date-based.md`, `outbox-pattern-netflix.md`
- 회사 슬러그 끝에 `-blog` suffix 안 붙임 (디렉토리가 이미 `company-tech-blogs/` 라 중복)
### 2.9 `raw/project-notes/<project-slug>.md`
- 형식: `<프로젝트 슬러그>.md`
- 예: `ca-skeleton-operational-contract.md`, `keycloak-patterns-overview.md`
- 프로젝트 슬러그는 frontmatter `related_projects:` 와 일치해야 함 (cluster 정합성)
### 2.10 `wiki/concepts/<concept-slug>.md`
- 형식: `<개념 슬러그>.md` (단수형 권장)
- 예: `idempotency.md`, `outbox-pattern.md`, `circuit-breaker.md`
- 일반 개념이므로 회사·프로젝트 슬러그 prefix 금지
### 2.11 `wiki/projects/<project-slug>/<topic>.md`
- 형식: 프로젝트별 subdirectory + 토픽 슬러그
- 예: `wiki/projects/ca-tmpl/config-and-adapter-templates.md`
- subdirectory 이름은 raw/project-notes/ 의 슬러그와 일치
- frontmatter `source_type: project` 사용 (`wiki-project-template.md` 기반). `raw/project-notes/<slug>.md``source_type: project-note` — 두 타입은 구분된다.
### 2.12 `wiki/interview/<question-slug>.md`
- 형식: `wiki/interview/<카테고리>/<질문 슬러그>.md` 또는 평면 구조
- 예: `wiki/interview/auth/jwt-vs-session.md`
- 카테고리 권장값: `auth`, `architecture`, `persistence`, `observability`, `messaging`, `testing`, `general`
### 2.13 `wiki/portfolio/<portfolio-slug>.md`
- 형식: `wiki/portfolio/<프로젝트 또는 주제 슬러그>.md`
- 예: `wiki/portfolio/ca-tmpl-clean-architecture.md`
### 2.14 `wiki/blog/<post-slug>.md`
- 형식: `wiki/blog/<글 슬러그>-<YYYY-MM-DD>.md` (날짜 suffix 권장 — drafts vs published 구분)
- 예: `wiki/blog/why-i-rejected-rfc-7807-2026-05-25.md`
## 3. 다이어그램 파일
### 3.1 도구 선택 (엄격)
- **시스템 아키텍처 / 컴포넌트 구성도 / 배포 토폴로지 / 데이터 흐름** → **draw.io XML** (`.drawio` 또는 `.drawio.svg`)
- **시퀀스** → **Mermaid `sequenceDiagram`** (project-note 본문 inline code block)
- **ER (선택)** → **Mermaid `erDiagram`** (본문 inline)
- 시스템 아키텍처를 Mermaid `graph TD`/`graph LR` 로 작성 금지
### 3.2 draw.io 파일 명명·저장
- 저장 경로: `raw/diagrams/<project-slug>/`
- 명명: `architecture-<viewpoint>-<YYYY-MM-DD>.drawio` (또는 `.drawio.svg`)
- viewpoint 예: `overview`, `deployment`, `data-flow`, `security`, `network`, `module-dependency`, `runtime-topology`
- archived: `raw/diagrams/<project-slug>/archived/`
- 확장자 선택:
- `.drawio` — 순수 XML (mxfile). git diff 친화, 단 Obsidian inline 렌더링은 플러그인 의존
- `.drawio.svg` — SVG 래퍼 + 내부 mxfile XML. Obsidian draw.io 플러그인이 inline 이미지로 자동 렌더링
- 권장: 처음 `.drawio` 로 작성 → Obsidian 에서 열어 저장하면 자동으로 `.drawio.svg` 변환 가능
### 3.3 Mermaid 명명·위치
- 별도 파일 X. 본문 inline ```mermaid``` code block.
- 시퀀스 다이어그램 1개당 1 code block. 한 파일에 여러 sequenceDiagram 가능.
## 4. Frontmatter `title:` 필드
파일명 슬러그와 별개로 사람이 읽기 좋은 title 을 frontmatter 에 적음:
- 형식: `<type> / <human readable title>`
- 예: `branch / feature-keycloak-oauth2-proxy-oidc-flow (P1A — oauth2-proxy 구성과 OIDC 흐름)`
- 예: `error / OIDC discovery 실패 (2026-05-25)`
- 예: `official-doc / Spring Boot Actuator — Endpoint Exposure & Security Defaults`
> title 의 괄호 안 메타 정보(예: `(P1A — ...)`)는 자유 형식. 슬러그가 표현하지 못하는 단계·패턴 ID 를 보완하는 용도. **슬러그 자체에 numbered hierarchy 가 들어가서는 안 된다 (§2.1.3).**
## 5. 슬러그 생성 도우미 규칙
긴 한국어 제목을 영문 kebab-case 슬러그로:
- 동사 → 명사형 (예: "OIDC 발견 실패" → `oidc-discovery-failure`)
- 회사·기술명은 음역 또는 영문 그대로 (예: 토스 → `toss`, 카카오 → `kakao`)
- 4~6 단어 이내 권장
- 약어는 본 프로젝트의 `tag-taxonomy.md` 동의어 표 따름
## 6. 검증 체크리스트
문서 작성 시 self-check:
- [ ] 파일명이 영문 kebab-case
- [ ] 카테고리 디렉토리에 맞는 명명 규칙 준수
- [ ] branch-note 라면 prefix **4종 (`feature-` / `fix-` / `chore-` / `experiment-`)** 중 정확히 하나
- [ ] **branch-note 슬러그가 구현 내용을 표현 (§2.1.2). `feature-X-1-2` 같은 numbered hierarchy 금지**
- [ ] **`develop-*` prefix 사용 안 함 (§2.1.1 — 제거됨)**
- [ ] **branch-note 의 계층 정보는 frontmatter `parent_branch:` + `## Parent` 섹션에만 존재 (슬러그에 인코딩 X)**
- [ ] 한글 파일명 사용 안 함
- [ ] 공백·언더스코어·CamelCase 사용 안 함
- [ ] frontmatter `title:` 에 사람이 읽기 좋은 표제 명시
- [ ] 다이어그램 파일은 `raw/diagrams/<project-slug>/` 에 저장
@@ -0,0 +1,92 @@
# rules/project-readiness-gate — project-note 작성 완성도 게이트
> `rules/` 의 방법론 규칙. project-note(프로젝트 hub) 1개가 **다른 작업의 출발점이 될 만큼 깊고 근거 있는가**를 판정한다.
> 기준선은 `raw/project-notes/ca-skeleton-operational-contract.md` 의 *caliber*(엄격성 수준)이다 — 그 노트의 *내용·섹션 구성을 복제하라는 게 아니다*. 프로젝트마다 내용도 섹션 조직도 다르며, 게이트는 *깊이·근거·분해 수준*만 강제한다.
> `branch-depth-gate`(브랜치 1개 착수 깊이)와 다른 층: 본 게이트는 *프로젝트 hub* 미시 게이트.
## 적용
- 대상: `raw/project-notes/*.md`.
- 실행: `/project-spec <slug> <목표>`**내부 마지막 단계** (독립 `/project-readiness` 커맨드 없음) →
1. **1차 결정론 검사** `.claude/hooks/wiki_structure_lint.py` (project 모드 — proxy + 링크)
2. **2차 의미 판정** `project-readiness-auditor` (아래 4축 — 노트와 링크된 소스를 읽고 의미로 판정)
- 본 게이트는 **read-only**. 노트를 편집하지 않으며 판정을 노트에 박지 않는다.
## 왜 결정론 계층이 *섹션명 매칭*이 아닌가
exemplar `ca-skeleton-operational-contract.md` 는 project-template §1~14 가 아니라 계약 특화 자기 구조(§1 목표 … §30 아키텍처 … §33 checklist)를 쓴다. "project-template 섹션 존재"를 강제하면 *exemplar 자신이 탈락*한다. 따라서 1차는 **구조-불가지 proxy**(섹션명 무관, 존재만)만 본다. *깊이/caliber* 는 전적으로 2차 auditor.
## 역할 분담 (결정론 proxy vs 의미)
| | 1차 린터(proxy, 존재) | 2차 감사기(LLM 의미, 깊이) |
|---|---|---|
| R1 문제·성공 구체성 | (해당 proxy 없음) | 측정가능 기준인가, 추상 표현("잘 동작")인가 |
| R2 아키텍처·시퀀스 | `PROJECT_NO_DIAGRAM` (임베디드 다이어그램 0개) | 다이어그램 *존재/placeholder* 여부 + 시퀀스 error path 유무 (컨퍼런스급 ≥95 는 판정 안 함 — `wiki-diagram-reviewer` 권고만) |
| R3 결정 근거성 | 링크 깨짐만 | 기술결정이 대안+외부근거로 뒷받침되나, 맨주장인가 |
| R4 Work Item 분해 | `PROJECT_NO_BRANCH_TABLE` (legacy 명칭; Work Item 표 부재) | 각 Work Item 이 stable ID + valid slug + 측정가능 완료조건 + pinned decision refs 를 가지는가 |
→ 2차 감사기는 **의미만** 본다(존재는 1차가 확인).
## 4축 (R1~R4)
> 축 라벨은 `R1~R4`. branch-depth-gate 와 동일 라벨 체계지만 *대상이 다르다*(branch 1개가 아니라 프로젝트 hub).
| 축 | Pass 조건 | Blocking(Not-ready) 트리거 |
|---|---|---|
| **R1. 문제·성공 구체성** | §문제정의가 구체 시나리오/수치, 성공기준이 측정가능 | 성공기준이 "잘 동작한다" 류 추상 표현뿐 |
| **R2. 아키텍처·시퀀스 깊이** | 아키텍처 다이어그램 **존재**(게이트가 확인하는 것은 *존재*만) + 핵심 시퀀스가 happy+error path | 다이어그램 *완전 부재* / 시퀀스가 happy path 만. ※ `needs-diagram` placeholder(사용자가 작성 예정)는 **Blocking 아님 → Should-fix(`DIAGRAM_PENDING_USER`)**. ※ 컨퍼런스급 `≥95` 는 게이트가 강제 못 함 — 사용자가 `wiki-diagram-reviewer` 별도 실행(아래 R2 ≥95 주) |
| **R3. 결정 근거성** | 각 주요 기술결정이 검토 대안 + 외부근거 wikilink(official/회사블로그) 보유 | 기술결정이 근거 없는 맨주장. ※ `deferred` 표시된 결정(자동조사 6개 bound 초과분)은 **R3 Blocking 면제 → Advisory** (현재 pass 에서 근거 미보유 허용, branch 단계에서 종결) |
| **R4. Work Item 분해 실행가능성** | 각 자식 작업이 `WI-<PROJECT>-NNN` stable ID + naming-conventions 준수 slug + 측정가능 완료조건 + `DEC-...@revision` pinned refs + 유효한 dependency 를 가짐. 결정 *내용*은 Work Item 표에 적지 않음. 표에 **실데이터 row ≥1**(placeholder 만 있으면 미충족) | Work Item Registry 부재 / 실 row 0 / ID·slug·완료조건·decision pin 누락 / 존재하지 않는 dependency |
> **R2 ≥95 주**: 게이트(린터 proxy·auditor)는 다이어그램의 *존재*만 확인하고 *품질 점수(≥95)는 확인하지 못한다* (auditor 는 `Read/Grep/Glob` 만 가져 `wiki-diagram-reviewer` 를 dispatch 못 함). 따라서 "다이어그램이 컨퍼런스급인가"는 **게이트의 Ready 조건이 아니라** 사용자가 `wiki-diagram-reviewer` 를 별도 실행해 확인하는 *권고 단계*다. Ready 판정은 *존재 + error-path 시퀀스*까지만 보장한다.
## 깊이 사다리 (R1~R4 공통)
| 레벨 | 항목이 답하는 것 | 판정 |
|---|---|---|
| **L0 존재** | "섹션이 있다 / 항목이 적혀 있다" | 단독 불충분 |
| **L1 메커니즘** | 어떻게/왜 — 구체 시나리오·메커니즘·근거 링크 | 최소선 |
| **L2 조건·경계** | 언제 적용/제외, 실패/대안, 측정 기준 | Ready 최소선 |
| **L3 검증** | 측정값·다이어그램 점수·검증 등급 근거 | 가산점 |
## 판정 규칙
- 심각도 3단계: `Blocking`(Not-ready) · `Should-fix`(권고) · `Advisory`(참고).
- **Ready = 4축 모두 L2+ (Blocking 0).** 이것이 "ca-skeleton caliber" 의 조작적 정의. Should-fix 가 남아도 사용자 "감수" 선언 시 진행 가능(리포트에 기록).
- 모든 finding 은 4종 세트로 근거화: `심각도 · 위치(섹션/행) · 예상 문제("이 hub 를 출발점 삼는 다음 작업자가 여기서 ___를 되묻게 됨") · 채울 방법`. 근거 없는 지적 금지.
- **세션 내 해소 불가 Blocking 의 탈출 (무한루프 방지)**: 일부 Blocking 은 *사용자 행동*으로만 해소된다(아키텍처 `.drawio` 작성, 사용자 소유 결정 입력). 이런 항목은 게이트·오케스트레이터가 **무한 재시도하지 않는다**. 판정을 `Ready-pending-user` 로 내고, *정확히 어떤 사용자 행동이 무엇을 unblock 하는지* 한 줄로 보고한 뒤 **깨끗이 종료**한다. 자동 루프백은 *자동으로 채울 수 있는* Blocking(근거 보강·시퀀스 error path 추가 등)에만 적용하며, **루프 천장 = 2회**(2회 후에도 동일 Blocking 잔존 시 종료+보고). `DIAGRAM_PENDING_USER`·사용자 소유 결정 미입력은 자동 루프 대상이 아니다.
## 명명된 실패 모드
- `ABSTRACT_SUCCESS_CRITERION` (R1): 성공기준이 측정 불가 추상 표현.
- `DIAGRAM_MISSING_OR_WEAK` (R2, **Blocking**): 아키텍처 다이어그램 *완전 부재*. (※ ≥95 품질 미달은 게이트가 판정 안 함 — R2 ≥95 주 참조.)
- `DIAGRAM_PENDING_USER` (R2, **Should-fix**): `needs-diagram` placeholder 존재(사용자 작성 예정). 자동 루프 대상 아님 → `Ready-pending-user`.
- `HAPPY_PATH_ONLY_SEQUENCE` (R2): 시퀀스에 error path 없음.
- `UNSOURCED_TECH_DECISION` (R3): 기술결정에 대안·외부근거 없음. (※ `deferred` 표시 결정은 면제 → Advisory.)
- `BRANCH_DECOMP_INCOMPLETE` (R4): 분해표 부재 / 실 row 0(placeholder 만) / slug·목표조건 누락.
### v2 project contract 실패 모드
- `MISSING_PROJECT_BINDING` (R4, Blocking): project 직접 자식 branch 의 `project` 또는 `work_item` binding 이 없거나, Work Item Registry 의 project/branch row 와 일치하지 않음.
- `MISSING_INHERITED_DECISION` (R4, Blocking): Work Item 의 `Applies Decisions` 에 있는 pinned ref 가 branch frontmatter `inherits` 또는 Branch Contract Packet 에 없음.
- `STALE_INHERITANCE_REVISION` (R4, Blocking): branch 가 pin 한 `DEC-...@revision` 이 project registry 의 현재 revision 보다 오래되었고 명시적 migration/override 상태도 없음.
- `CONFLICTS_WITH_PROJECT_DECISION` (R4, Blocking): branch-local 결정 또는 구현 계약이 inherited project decision 과 양립하지 않는데 승인된 override 가 없음.
- `UNDECLARED_OVERRIDE` (R4, Blocking): branch 가 project 결정을 다르게 적용하면서 frontmatter `overrides``Declared Overrides` 표에 같은 pinned ref·이유·승인을 선언하지 않음.
- `MISSING_EXPECTED_EDGE` (R4, Blocking): Work Item 이 요구하는 project→branch, WI dependency, decision inheritance edge 중 하나가 실제 branch packet 에 없음.
- `DUPLICATE_DECISION_OWNER` (R3, Blocking): 같은 stable project Decision ID 또는 동일 계약 관심사를 둘 이상의 owner row/document 가 소유함.
## v1 legacy 호환 정책
- active `raw/project-notes/*.md``raw/branch-notes/*.md`는 2026-07-20 migration 이후 v2 graph contract를 필수로 가진다.
- marker/table이 없는 문서는 `raw/archive/` 또는 `vault/90-archive/`에서만 보존하며 graph·structure 전수 검사 대상에서 제외한다.
- 외부 저장소에서 legacy 문서를 다시 가져오면 `LEGACY_PROJECT_CONTRACT` warning으로 식별하되, active 경로로 승격하기 전에 stable Decision/Work Item/Branch ID와 계약 패킷을 부여한다.
- `/project-spec`는 본문 결정을 추측해 변환하지 않고, stable ID 부여가 모호하면 사용자 결정을 요청한다.
## proxy(1차 결정론) — `wiki_structure_lint.py` project 모드
- `PROJECT_NO_DIAGRAM` — 임베디드 다이어그램 0개(`![[....drawio` 임베드도 ```mermaid 블록도 없음). R2 존재 proxy.
- `PROJECT_NO_BRANCH_TABLE` — legacy 코드명. Work Item Registry(또는 legacy Branch 분해표) 부재. R4 존재 proxy.
- `MISSING_FRONTMATTER` — project-template frontmatter 필수 키 누락(기존 검사 재사용).
- C2 링크(BROKEN_LINK 등) — 그대로.
proxy 는 *존재* 만 본다. 임베디드 다이어그램이 컨퍼런스급인지, 분해표 row 가 측정가능한지는 2차 auditor 가 판정한다.
+40
View File
@@ -0,0 +1,40 @@
# rules/prose-style — 한국어 작성 원칙 (윤문은 외부 하네스로 이관)
> `rules/` 의 방법론 규칙입니다.
> **2026-07-21 변경:** 한국어 문체·자연스러움 검사와 윤문 책임을 이 저장소에서 **제거**하고 별도 하네스 [im-not-ai](https://github.com/) (`/humanize-korean`) 로 이관했습니다.
> 이 문서에는 llm-wiki 가 계속 책임지는 두 가지 — **한국어로 쓴다**는 원칙과 **사실 경계** — 만 남깁니다.
## 왜 이관했나
문서를 쓰는 도중에 문장 단위로 윤문을 검사하면, 문서 한 편에 시간이 과도하게 들고 검사 지점이 잘게 쪼개져 실패 지점만 늘어납니다. 윤문은 본래 **문서를 다 쓴 뒤 한 번에 훑는 작업**이고, 그걸 전문으로 하는 하네스가 이미 있습니다.
- llm-wiki 의 책임: 구조·계약·근거·의미 정합 (`quality_gate`, `typed_contract_check`, semantic certificate)
- im-not-ai 의 책임: 한국어 자연스러움, AI 티 제거, 번역투 교정
## 1. 작성 원칙 (llm-wiki 책임)
- **본문은 한국어로 씁니다.** 영어 단어를 습관적으로 섞지 않습니다.
- **개발·기술 용어는 원문(주로 영어)을 유지합니다.** 예: `connection pool`, `idempotent`, `latency`, `circuit breaker`, `transaction`. 억지로 한글화하지 않습니다.
- 코드, CLI 명령어, 설정 키, 에러 메시지, 계약 ID(`FE-OC-001`, `DEC-...@1`)는 그대로 인용합니다.
- 표현이 다소 어색해도 **작성 단계에서는 넘어갑니다.** 문체 교정은 아래 §3 의 마무리 단계에서 일괄 처리합니다.
## 2. 사실 경계 (llm-wiki 책임 — 이관 대상 아님)
윤문은 표현만 다듬고 **사실 등급을 바꾸지 않습니다.** `documented-only` · `planned` · `needs-confirmation` 을 매끄러운 문장으로 포장해 검증된 것처럼 보이게 하면 안 됩니다(CLAUDE.md §6, §11). 과장 표현(`최적화했다`, `X배 개선`, `운영 중`)은 근거 등급이 받쳐줄 때만 씁니다.
- `POLISHED_OVERCLAIM` — 윤문으로 미검증 사실을 검증된 것처럼 포장. **이관 후에도 llm-wiki 가 검사합니다.**
im-not-ai 로 윤문을 돌린 뒤에도 이 경계는 다시 확인해야 합니다. 자연스러움을 높이는 과정에서 단정 표현이 강해질 수 있기 때문입니다.
## 3. 윤문 실행 (im-not-ai)
문서 작성이 끝난 뒤, 개별 문서가 아니라 **작업 묶음 단위로 한 번** 실행합니다.
```text
경로: /home/donghyeon/workspace/ai-tool/im-not-ai
호출: /humanize-korean (Claude) · $humanize-korean (Codex)
```
- 대상: 파생 산출물(`40-publish/` interview · blog · portfolio)과 사람이 읽을 문서.
- 설계 문서(`10-projects/` project-note · branch-note)는 AI 가 읽는 용도이므로 **필수 아님** — 용어가 뒤섞여 읽기 힘들 때만 돌립니다.
- 실행 후 §2 사실 경계를 재확인합니다.
@@ -0,0 +1,564 @@
# Reporting Standards Rule
This rule defines the **language and format contract** for every multi-file, audit, review, brainstorming, research, or evaluation report the agent produces in this workspace.
It applies to: wiki research-lane reports, multi-file document audits, raw → canonical extraction recommendations, link integrity audit reports, adversarial review reports, brainstorming summaries on documents, and any final response that touches more than one wiki file.
It does **not** apply to: trivial single-file edits, short Q&A on one location, or shell command outputs.
**Scope note:** 본 rule은 LLM Wiki 문서 작업의 보고서에 적용된다. 코드(Java/Clean Architecture) 작업의 보고서는 ca-tmpl `.agents/plugins/ca-superpowers/rules/reporting-standards.md` 를 따른다 — 본 rule과 90% 동일하지만 §0 alias, §4 Automated 검증, §7.2 빌드 명령이 코드 컨텍스트로 채워져 있다.
## Language Contract
The agent writes report prose in the **same language the user used in the current task**.
- If the user wrote the task in Korean, the report body is Korean.
- If the user wrote in English, the report body is English.
- If the user mixed languages, match the dominant language. If unclear, ask before writing.
**Always English regardless of user language:**
- Section field names in the template below (`Verdict`, `Evidence Matrix`, `Status`, etc.).
- Status values (`READ_FULL`, `READ_PARTIAL`, `NOT_READ`, `BLOCKED`).
- Named failure labels (`FACT`, `INFERENCE`, `FILENAME_INFERENCE`, `MEMORY_HALLUCINATION`, `CONFIDENCE_WITHOUT_READ`, `BATCH_ASSUMPTION`, `UNVERIFIED`).
- File paths and identifiers (`raw/branch-notes/<slug>.md`, `wiki/concepts/<slug>.md`, wikilink targets `[[...]]`, frontmatter field names).
The agent does **not** write the analysis body in one language and a parallel summary in another. One body, one language, the user's language.
If the agent finds itself writing the report in English when the user wrote in Korean (or vice versa), it stops, deletes the draft, and rewrites in the correct language. This is a hard rule, not a preference.
## Output Split Policy
Long reports must be **split across files**, not dumped into the terminal. The terminal carries the navigation layer; the disk carries the depth.
### When to split
The agent splits the response into disk artifacts + terminal summary whenever **any one** of the following is true:
- Report touches **more than 3 in-scope files** (per the user's stated scope or the evidence matrix).
- §4 Per-File Findings would contain **5 or more subsections**.
- The full §1~§7 response would exceed approximately **10,000 characters** (rough threshold; the agent estimates before sending).
- The user said "save", "저장", "파일로", "report", "보고서" with respect to a multi-file or multi-finding task.
For one-off single-file questions, trivial lookups, or short advisory answers, **do not split** — the full content stays in the terminal.
### What to save
산출물 유형별로 저장 경로가 다르다. **메타 보고서**(작업 자체에 대한 audit/research report)는 `docs/superpowers/specs/` 에, **wiki 산출물**(canonical 문서, derived 문서)은 `wiki/` 하위에 저장된다. CLAUDE.md §15 파이프라인 게이트가 강제됨:
| 산출물 유형 | 저장 경로 | 게이트 (rule이 강제) |
| --- | --- | --- |
| Multi-doc audit / research report (예: `branch-notes-audit`, `link-integrity-audit`) | `docs/superpowers/specs/YYYY-MM-DD-<topic>-report.md` (+ per-file-findings) | — |
| 신규 raw 문서 (URL 요약, branch-note 등) | `raw/<category>/<slug>.md` | `wiki-doc-author` 또는 `wiki-source-summarizer` agent dispatch |
| Canonical 추출 (raw → wiki/concepts 또는 raw → wiki/projects) | `wiki/concepts/<slug>.md` 또는 `wiki/projects/<project>/<topic>.md` | **`/ingest` 게이트만 허용** — agent가 직접 `wiki/interview/`, `wiki/portfolio/`, `wiki/blog/` 에 작성 금지 |
| Derived (interview / portfolio / blog) | `wiki/interview/[<cat>/]<slug>.md`, `wiki/portfolio/<slug>.md`, `wiki/blog/<slug>-YYYY-MM-DD.md` | **원천 canonical 문서 status ∈ {reviewed, verified, published-ready}** 필수. 미달 시 BLOCKED |
| Adversarial review report | `docs/superpowers/specs/YYYY-MM-DD-<topic>-adversarial-review.md` | findings ≥ 5 시 권장 |
메타 보고서의 경우 두 파일을 쓴다:
1. **`docs/superpowers/specs/YYYY-MM-DD-<topic>-report.md`** — the master report.
- Contains §1 Executive Summary, §2 Evidence Matrix, §3 Coverage Reconciliation, §4 (one-line per-file summary with link to file 2), §5 Priority Recommendations, §6 Follow-Up, §7 Verification, §8 Generated Artifacts.
- This is the document anyone should be able to read top-to-bottom to understand the audit.
2. **`docs/superpowers/specs/YYYY-MM-DD-<topic>-per-file-findings.md`** — full per-file depth.
- Contains expanded §4 with one subsection per `READ_FULL` / `READ_PARTIAL` file.
- Each subsection follows the deep Per-File Finding template (Goal / Current / Gap / Action / Why / Alternatives / Implementation Steps / Verification Approach / Related).
- Multiple findings per file when the analysis surfaces multiple gaps. Do not artificially limit to one finding per file.
Naming rules:
- `YYYY-MM-DD` is today's date (the day the report is produced).
- `<topic>` is a short kebab-case slug. Examples: `branch-notes-audit`, `link-integrity-audit`, `keycloak-patterns-canonical-extraction`, `wiki-concepts-promotion-review`.
- If a file with the same name already exists, append `-v2`, `-v3`, etc. — never overwrite a prior report without an explicit user instruction.
### Pipeline Gate Enforcement (CLAUDE.md §15)
본 rule은 다음을 hard rule 로 강제한다. 위반 시 draft `BLOCKED`:
1. **`wiki/interview/`, `wiki/portfolio/`, `wiki/blog/` 에 직접 작성 금지** — agent가 이 경로에 새 파일을 쓰려 하면 즉시 멈추고 `NEEDS_CONTEXT` 반환. 이 경로는 `/projectize`, `/interviewize`, `/blogify` 슬래시 커맨드 또는 수동 작성 전용.
2. **derived 문서 작성 전 원천 canonical 문서의 status 확인 강제** — 원천 status가 `reviewed | verified | published-ready` 미만이면 BLOCKED. agent는 응답에 `원천 <canonical-path> status: <value>` 명시 + status 검증 grep 출력 첨부.
3. **`/ingest`의 목적지는 `wiki/concepts/``wiki/projects/` 만** — 다른 wiki 하위 디렉토리로의 ingest 금지. `raw/daily-notes/`, `raw/branch-notes/` 자체는 보존하고 항목 단위 추출만.
4. **canonical 문서의 Sources 필수**`wiki/concepts/``wiki/projects/` 작성 시 외부 자료(`raw/official-docs/` 또는 `raw/company-tech-blogs/`) wikilink 1개 이상이 본문에 없으면 BLOCKED.
### What stays in the terminal
The terminal response carries **only** the navigation layer:
```markdown
# [작업명] 보고서 — 터미널 요약
**일자:** YYYY-MM-DD
**범위:** <N개 파일>
**Verdict:** COMPLETE | PARTIAL | BLOCKED
**전체 보고서:** [docs/superpowers/specs/YYYY-MM-DD-<topic>-report.md](./docs/superpowers/specs/...)
**파일별 상세:** [docs/superpowers/specs/YYYY-MM-DD-<topic>-per-file-findings.md](./docs/superpowers/specs/...)
## 1. 한눈 요약 / Executive Summary
(전체본)
## 2. Evidence Matrix
(전체본; 행 수가 많아도 매트릭스는 터미널에 그대로 둔다 — 검증 가능성이 핵심)
## 5. 우선순위 권고 / Priority Recommendations
(전체본; 표는 터미널에 그대로 둔다)
## 6. 후속 작업 / Follow-Up
(전체본)
## 7. 검증 / Verification
(실행한 명령 + 결과)
```
**터미널에서 생략하는 섹션:** §3 Coverage Reconciliation 상세, §4 Per-File Findings 본문(요약 한 줄만), §8 Generated Artifacts (위 frontmatter 링크로 대체).
§4 Per-File Findings를 터미널에 그대로 붙여넣어 출력을 부풀리지 않는다. 터미널은 사용자의 작업 흐름을 끊지 않을 분량을 유지한다.
### Link format
Saved file path는 워크스페이스 루트(저장소 최상단) 기준 상대 경로로 적는다. 절대 경로 금지.
예시:
```markdown
- 전체 보고서: `docs/superpowers/specs/2026-05-23-branch-notes-audit-report.md`
- 파일별 상세: `docs/superpowers/specs/2026-05-23-branch-notes-audit-per-file-findings.md`
```
### Pre-send check (split-specific)
송신 직전, 분할이 필요한 작업인 경우 다음을 확인한다. 하나라도 실패하면 draft 폐기.
1. 두 파일이 실제로 디스크에 쓰여 있는가? (Write 도구 실행 결과 확인)
2. 터미널 본문에 두 파일의 상대 경로 링크가 포함되었는가?
3. 터미널 본문이 §4 Per-File Findings 상세를 포함하지 않는가? (요약 한 줄만 허용)
4. 두 파일이 §1~§7 (master) / §4 expanded (per-file)을 각자 자기 위치에서 완비하는가?
5. 두 파일의 헤더 frontmatter (일자, 범위, Verdict)가 서로 일치하는가?
## Report Template
Every covered report follows this exact section order. Sections cannot be reordered, merged, or omitted. Empty sections are written explicitly with `해당 없음 / N/A` rather than dropped.
```markdown
# [작업명] 보고서 (또는 [Task] Report - 사용자 언어 일치)
**일자 / Date:** YYYY-MM-DD
**범위 / Scope:** <N개 파일 또는 영역>
**Verdict:** COMPLETE | PARTIAL | BLOCKED
**요청 언어 / User language:** ko | en | mixed
## 0. Source roots (외부 디렉토리 참조 시에만)
본 보고서가 워크스페이스 밖의 파일을 인용하는 경우, 짧은 alias를 절대 경로에 매핑한다.
이후 §2~§7의 모든 인용은 alias 기반의 워크스페이스 상대 경로 또는 alias 표기를 사용한다.
| Alias | 절대 경로 |
| --- | --- |
| `<raw-branches>` | `<workspace-root>/raw/branch-notes` |
| `<raw-projects>` | `<workspace-root>/raw/project-notes` |
| `<wiki-concepts>` | `<workspace-root>/wiki/concepts` |
| `<wiki-projects>` | `<workspace-root>/wiki/projects` |
| `<external-code>` | `<사용자가 지정한 external root>` (코드 컨텍스트 참조 시) |
이후 인용 예: `<raw-branches>/feature-keycloak-oauth2-proxy-oidc-flow.md:42` 또는 `<wiki-concepts>/idempotency.md:18`.
(워크스페이스 안 파일만 다루는 보고서는 본 섹션을 "해당 없음 / N/A" 로 명시한다.)
## 1. 한눈 요약 / Executive Summary
3~6 문장. 다음을 포함한다:
- 무엇을 했는가
- 정독한 파일 수 / 전체 in-scope 파일 수
- 가장 중요한 발견 1~2가지
- 후속 조치가 필요한 항목 수
## 2. Evidence Matrix
모든 in-scope 파일에 대해 정확히 한 행. 누락 금지.
| Path | Status | Evidence | Extracted facts |
| --- | --- | --- | --- |
| <path> | READ_FULL | <line range> | <facts in user language> |
| <path> | NOT_READ | <reason> | UNVERIFIED |
allowed Status: `READ_FULL`, `READ_PARTIAL`, `NOT_READ`, `BLOCKED`.
## 3. 커버리지 정합성 / Coverage Reconciliation
본 섹션은 자기 신고 영역이 아니라 **산식 영역**이다. 에이전트는 아래 값을 계산해서 채우고, 룰이 정의한 Verdict 결정 알고리즘에 따라 상단 Verdict 필드를 결정한다.
| 항목 | 값 |
| --- | --- |
| (a) 사용자가 명시한 파일 수 (또는 in-scope 파일 수) | <N> |
| (b) §2 evidence matrix 총 행 수 | <M> |
| (c) §2에서 Status가 `READ_FULL` 또는 `READ_PARTIAL`인 행 수 | <R> |
| (d) §4 파일별 분석 하위섹션 수 (deep 템플릿 충족) | <P> |
| (e) 차이 (a b) — 매트릭스 누락 | <a-b> |
| (f) **분석 깊이 미달 파일 수 (c − d)** — 매트릭스엔 READ_FULL이나 §4 분석 없음 | **<c-d>** |
### 분석 깊이 미달 파일 명세
`(c d) > 0` 인 경우, 아래에 누락된 파일들을 빠짐없이 나열한다. "차이 0" 또는 "없음"이라 적었으나 실제로 누락이 있으면 정직성 위반으로 자동 `BLOCKED`.
| 파일 경로 | §2 Status | §4 분석 여부 | 누락 사유 |
| --- | --- | --- | --- |
| `<raw-branches>/<slug>.md` | READ_FULL | ✗ 없음 | <시간 부족 / 분석 못 함 / 후속 처리 예정 등> |
| ... | ... | ... | ... |
(이 표가 비어 있다면 그 자체로 명시: "분석 깊이 미달 없음 — (c d) = 0".)
### `NOT_READ` / `BLOCKED` 파일
- `NOT_READ` 파일 목록: <list 또는 "없음">
- `BLOCKED` 파일 목록 (사유 포함): <list 또는 "없음">
### 정직성 컨트랙트
- 본 보고서의 모든 사실 주장은 §2 매트릭스의 `READ_FULL` / `READ_PARTIAL` 행에서 나온다.
- §4에서 다루지 않은 파일에 대한 권고는 §5에 등장할 수 없다.
- 매트릭스 행 수가 §4 하위섹션 수와 다른 경우, §4에 없는 파일을 §5 우선순위 표에 올리면 자동 `BLOCKED`.
## 3-1. Verdict 결정 알고리즘 / Verdict Calculation
상단 frontmatter의 `Verdict` 필드는 다음 산식으로 결정된다. 에이전트가 자기 의지로 라벨을 정하지 않는다. 산식과 라벨이 어긋나면 보고서는 송신 불가.
```text
Let:
N = 사용자가 명시한 in-scope 파일 수 (또는 자동 enumerate 결과)
M = §2 evidence matrix 총 행 수
R = §2에서 Status가 READ_FULL 또는 READ_PARTIAL인 행 수
P = §4 deep-template 충족 하위섹션 수
G = self-grep 검증 (advisory-depth Contract 6) 통과 finding 수
T = 전체 finding 수
Verdict =
COMPLETE iff (M == N) AND (P == R) AND (G == T) AND (모든 §5 권고가 §4 파일을 가리킴)
PARTIAL iff (M == N) AND ((P < R) OR (G < T)) — 매트릭스는 완비됐으나 §4 분석 또는 인용 검증이 부분적
BLOCKED iff (M < N) OR (in-scope 파일 enumeration 불가) OR (필수 first reads 차단)
```
`Verdict: COMPLETE`라고 적으려면 위 4개 조건이 **전부 참**이어야 한다. 한 조건이라도 거짓이면 라벨은 자동으로 `PARTIAL` 또는 `BLOCKED`로 강등된다. 에이전트는 산식 결과와 일치하지 않는 라벨을 적을 수 없다.
Pre-send 단계에서 §3의 (a)~(f) 값을 실제로 계산해 보고, 그 값으로 위 산식을 평가한 뒤 Verdict 라벨을 채운다. 산식 위반은 정직성 실패이며 draft는 폐기된다.
## 4. 파일별 발견 사항 / Per-File Findings
> **분할 시:** 본 §4의 상세는 `<topic>-per-file-findings.md` 파일에 들어간다. master report의 §4는 파일당 한 줄 요약 + 파일별 findings 문서 링크만 남긴다. 분할이 적용되지 않는 작은 보고서는 §4 상세가 master report에 그대로 포함된다.
각 파일은 자기 자신의 하위섹션을 갖는다. 파일을 "Pillar", "Group", "Theme" 등으로 묶지 않는다. 묶으면 누락이 숨겨진다.
각 발견 사항은 **Goal → Problem → Action 인과 사슬** 형식을 따른다. 단순 의견("성능이 떨어질 수 있다", "고려가 필요하다")은 금지. 자세한 컨트랙트는 `rules/advisory-depth.md` 의 Contract 1을 따른다.
### 한 파일에서의 finding 개수
각 파일에 대해 분석이 surfacing한 **모든 gap을 finding으로 등재한다.** 1개 파일 = 1개 finding이 아니라, 정독 결과 발견된 모든 결함·누락·모호점을 빠짐없이 풀어쓴다. 일반적으로 한 명세 파일에서 2~5개의 finding이 나오는 것이 정상이다.
### Single-finding Justification Gate
파일당 finding이 정확히 1개라면, 해당 §4 하위섹션 끝에 **반드시** 다음 정당화 블록을 첨부한다. 정당화 없이 1개로 끝낸 파일은 자동 `BLOCKED`.
```markdown
#### Single-finding justification (필수, finding이 1개일 때)
이 파일에서 단일 finding으로 종결한 이유를 다음 4개 중 1개 이상에 해당시켜 명시한다:
- [ ] **단순 명세:** 이 파일은 짧고 단일 결정만 다룬다 (파일 총 라인 수 < 80, 또는 단일 정책 명세).
증거: `<raw-branches>/<slug>.md` 총 <N>줄, 결정 사항 1건.
- [ ] **전수 통과 + 1개 결함:** 검토한 <K>개 항목 중 (K−1)개가 명세 의도와 일치하고, 1개만 결함.
검토 항목 리스트:
1. <item 1> — PASS
2. <item 2> — PASS
3. <item 3> — FAIL (위 finding)
...
- [ ] **부분 분석 (PARTIAL):** 시간·범위 제약으로 인해 1개만 분석했다. 추가 분석이 필요한 항목을 §6 Follow-Up에 명시했다.
남은 분석 대상: <list>
- [ ] **단일 critical 문제로 인한 차단:** 발견된 1개 finding이 너무 critical하여 다른 항목 분석에 앞서 우선 처리되어야 한다.
이유: <근거>
```
이 블록이 없거나, 4개 옵션 중 어느 것도 체크되지 않았거나, "검토 항목"이 비어 있는 경우 → 자동 `BLOCKED`. 정당화는 fluff가 아니라 **사실 진술**이어야 한다.
### Zero-finding 파일 처리
발견 사항이 진정 0개인 `READ_FULL` 파일은 하위섹션을 생략하지 않는다. 대신 명시한다:
```markdown
**0-finding 정당화 (필수):**
이 파일은 명세 의도(`Original goal`)와 현재 상태가 일치하며, 검토한 <N>개 항목 모두 통과. 추가 작업 불필요.
검토 항목:
1. <item 1> — PASS — 근거: `<file:line>`
2. <item 2> — PASS — 근거: `<file:line>`
...
```
`<N>개 항목`은 추상적이 아니라 실제 목록이어야 한다. "검토한 항목 모두 통과" 한 줄로 끝내면 자동 `BLOCKED`.
### 4.1 `<filename>` (Status: READ_FULL | READ_PARTIAL)
- **요지 / Gist:** <한 문장으로 이 파일이 무엇을 정의하는가>
- **문서 원래 목표 / Original goal of this file:** <이 파일이 정의하려 한 핵심 의도>. 근거: `<file:line>`
- **검토 항목 / Items reviewed:** <이 파일에서 점검한 N개 항목 리스트>
- **Findings 요약:** N개 (Critical X · High Y · Medium Z · 통과 W)
#### Finding 4.1.1: <짧은 라벨 — 이 finding의 한 문장 정체성>
- **심각도 / Severity:** Critical | High | Medium | Low
- **원래 목표 / Original goal:**
- 인용 / Verbatim quote: "<exact text from source, byte-for-byte>"
- 위치 / Source location: `<path>:<line>` (or `<path>:<start>-<end>` for ranges; workspace-relative paths only)
- 해석 / Interpretation: <한 문장으로 이 인용의 의도 해석>
- **현재 상태 / Current state:**
- 인용 / Verbatim quote: "<exact text from source>" (또는 "해당 라인 없음 — 명세 자체에 누락")
- 위치 / Source location: `<path>:<line>`
- **실무 가정 / Real-world assumptions (REQUIRED — minimum 1, typical 2~3):**
이 비판이 성립하려면 어떤 실무 가정이 참이어야 하는가? 명시하지 않으면 비판은 "에이전트가 상상한 구현"을 표적으로 삼게 됨.
1. **가정 A:** <e.g., "구현이 동기식일 것", "프로덕션 트래픽 > 1000 RPS", "K8s 환경", "사용자가 추가 구성 없이 디폴트만 적용함">
- **무효 조건 / Falsifies if:** <이 가정이 거짓일 구체적 시나리오>
- **사용자가 확인하는 방법 / How user verifies in their context:** <한 줄 체크>
2. **가정 B:** ...
3. **가정 C:** ...
- **간극 / Gap (위 가정들이 모두 참일 때):**
- **구체적 실패 모드 / Concrete failure mode:** <X 상황에서 Y가 발생하여 Z가 깨진다 — 1~3개 명시>
- **재현 조건 / Reproduction condition:** <이 실패가 실제로 일어나는 트리거>
- **이 finding이 무효해지는 경우 / When this finding doesn't apply:** <어떤 가정이 거짓이면 비판 자체가 사라지는가>
- **필요 조치 / Required action:** <구체 액션 — 추상적 권고 아닌 실행 가능한 형태>
- **조치 근거 / Why this action:** <왜 이 액션이 일반적 대안보다 이 상황에 맞는가, 위 가정 하에서>
- **대안 / Alternatives considered:** advisory-depth Contract 2에 따라 가능한 모든 정전 대안을 열거 (보통 3~5개)
- **대안 A:** <라벨> — 적용 상황 / 부적합 이유
- **대안 B:** <라벨> — 적용 상황 / 부적합 이유
- **대안 C (채택):** <라벨> — 왜 이 상황에 가장 맞는가
- **대안 D, E ...:** 가능한 경우 모두 열거
- **반대 논거 / Counterarguments (REQUIRED — minimum 1, typical 2~3):**
advisory-depth Contract 1에 따라, 이 권고가 틀릴 수 있는 시나리오를 명시한다.
1. **반대 A:** <이 권고가 부적절·과잉인 시나리오>
- **반대 근거:** <왜 그 시나리오에서는 권고가 부적절한가>
- **사용자가 검증하는 방법:** <한 줄 체크>
2. **반대 B:** ...
- **구현 단계 / Implementation steps:** <Required action을 실제로 적용하기 위한 순서 있는 단계>
1. <단계 1 — 수정할 파일, 어디에 어떤 코드/문장이 들어가는지>
2. <단계 2>
3. <단계 3>
- **검증 방법 / Verification approach:** <조치가 실제로 작동하는지 입증하는 방법>
- **자동 검증 / Automated:** <self-grep 명령 / `wiki-link-verifier` agent dispatch / `/lint` 슬래시 커맨드 / frontmatter 필드 grep / wikilink ls 검증 등>
- **수동 검증 / Manual:** <Obsidian 그래프뷰 확인 / 리뷰 시 확인할 포인트 (자동 검증으로 부족할 때만)>
- **관련 / Related:**
- **다른 finding과의 결합:** <같은 파일 또는 다른 파일의 finding과 함께 처리해야 효과가 나는 경우>
- **상호 의존 파일:** <이 조치가 영향을 주거나 받는 다른 명세/모듈>
#### Finding 4.1.2: ...
(반복)
### 4.2 `<next filename>` ...
`NOT_READ``BLOCKED` 파일은 본 섹션에 자기 하위섹션을 갖지 않는다. 매트릭스와 §3에만 등장한다.
### Master report에서의 §4 (분할 시)
분할이 적용된 경우, master report의 §4는 다음 형식의 한 줄 요약 표만 남긴다:
```markdown
## 4. 파일별 발견 사항 / Per-File Findings (요약)
> 상세: [<topic>-per-file-findings.md](./docs/superpowers/specs/<topic>-per-file-findings.md)
| # | File | Findings | Critical | High | Medium | Low | 통과 |
| --- | --- | --- | --- | --- | --- | --- | --- |
| 4.1 | `feature-X.md` | 3 | 1 | 2 | 0 | 0 | N/A |
| 4.2 | `feature-Y.md` | 2 | 0 | 1 | 1 | 0 | N/A |
...
```
## 4-1. 적대 리뷰 결과 / Adversarial Review Results
본 섹션은 적대 리뷰 서브에이전트가 §4의 각 finding에 대해 수행한 falsification 검토 결과를 요약한다. wiki-superpowers 플러그인의 주 작업은 multi-doc audit / raw → canonical 추출 권고 / 링크 무결성 감사이며, findings 가 5개 이상일 때 `wiki-adversarial-reviewer` 디스패치를 권장한다. 5개 미만이면 적대 리뷰 없이 송신 가능. 코드(Java/CA) 작업의 적대 리뷰는 본 플러그인 범위 밖이며, ca-tmpl 코드 리뷰 체인(`ca-architect-sentinel``ca-spec-reviewer``ca-quality-reviewer`) 이 separation of concerns 를 제공한다.
분할 시: 본 섹션은 master report에 들어간다. per-file-findings 문서에는 들어가지 않는다.
### 4-1.1 적대 리뷰 실행 여부
| 항목 | 값 |
| --- | --- |
| 적대 리뷰 실행 여부 | YES / NO |
| 실행하지 않은 사유 (NO 시) | <e.g., findings 수 < 5라 oversight 불필요 / 빠른 turnaround 요구로 생략> |
| 적대 리뷰 보고서 경로 (실행 시) | `docs/superpowers/specs/YYYY-MM-DD-<topic>-adversarial-review.md` |
§4 findings가 5개 이상이거나 master report가 priority recommendation을 §5에 4개 이상 올린다면 적대 리뷰를 **권장**한다. 5개 미만의 작은 보고서는 적대 리뷰 없이도 무방.
### 4-1.2 적대 리뷰 요약 표 (실행 시)
| Finding ID | Original severity | Practicality | Overclaim | Assumption | Action |
| --- | --- | --- | --- | --- | --- | --- |
| 4.1.1 | Critical | PASS | FAIL | PASS | DOWNGRADE → High |
| ... | ... | ... | ... | ... | ... | ... |
### 4-1.3 컨트롤러 판단 반영
각 finding에 대해 컨트롤러가 적대 리뷰 권고를 수용·거부한 내역을 명시한다:
- **수용 (Accept)**: 적대 리뷰 권고대로 severity 강등 또는 finding 제거 적용.
- **거부 (Override)**: 컨트롤러가 적대 리뷰 권고를 거부. 거부 사유 1~2줄 명시 필수.
| Finding ID | 적대 권고 | 컨트롤러 결정 | 거부 사유 (Override 시) |
| --- | --- | --- | --- |
| 4.1.1 | DOWNGRADE → High | Accept | — |
| 4.2.1 | REJECT | Override (KEEP at Medium) | 사용자 환경에서 실제로 관측된 사례, 제거 부적절 |
### 4-1.4 결과 메트릭
- KEEP: <n>
- DOWNGRADE: <n>
- REJECT: <n>
- Override: <n>
§1 Executive Summary와 §5 Priority Recommendations는 위 결과 반영 후의 상태를 반영해야 한다. 적대 리뷰 후 강등된 finding이 §5에 여전히 P0/Critical로 올라 있으면 자동 BLOCKED.
## 5. 우선순위 권고 / Priority Recommendations
| 우선순위 | 권고 액션 | 근거 파일:라인 | 원래 목표 | 현재 간극 | 조치 후 효과 |
| --- | --- | --- | --- | --- | --- |
| 1 (Critical) | ... | `<file:line>` | ... | ... | ... |
| 2 (High) | ... | `<file:line>` | ... | ... | ... |
각 행은 §4의 한 Finding과 1:1 대응되어야 한다. 행을 §4보다 단순화·축약·일반화하지 않는다.
본 표에 등장하는 모든 파일은 §4에 자기 하위섹션을 가진 `READ_FULL` 또는 `READ_PARTIAL` 파일이어야 한다.
§4에 없는 파일을 본 표에 올리면 자동으로 `BLOCKED`. 보고서를 송신하지 않는다.
## 6. 후속 작업 / Follow-Up
- 다음 라운드에서 정독해야 할 파일
- 미해결 위험
- 추가 검증이 필요한 가설
## 7. 검증 / Verification
### 7.0 Proof manifest v2 (신규 run의 SSOT)
신규 report run의 quote proof SSOT는 `proof-manifest/v1` JSON이다. schema와 실행 profile은 각각 [`harness/runtime/proof_manifest.py`](../harness/runtime/proof_manifest.py), [`harness/source/execution-profiles.json`](../harness/source/execution-profiles.json)에 두며, profile 선택 규칙은 [`rules/execution-profiles.md`](execution-profiles.md)를 따른다. 신규 run은 draft의 finding-role·source path·exact quote를 `proof-request/v1`으로 만든 뒤 `proof_runner.py`가 manifest와 compact summary를 함께 쓰는 경로를 사용한다.
```bash
python3 harness/runtime/proof_runner.py '<proof-request.json>' \
--repo-root . \
--output 'docs/superpowers/specs/<topic>/proof-manifest.json' \
--summary-output 'docs/superpowers/specs/<topic>/proof-summary.md'
```
- runner exit code가 `0`이고 stdout `proof-runner-result/v1.status`와 output의 `verification.status`가 모두 `PASS`인 proof만 `P``G`에 포함한다. 실패 시 manifest와 summary를 쓰지 않으며 보고 완료 판정을 중단한다.
- §7.1 Markdown에는 generated `proof-summary.md`의 manifest 경로, proof/PASS/FAIL count, **persisted manifest bytes의 SHA-256**을 반영하고, hash를 실제 manifest bytes와 다시 대조한다.
- 본문에는 실패 proof·라인 정정·대표 PASS proof 1~3개만 펼친다. 나머지 PASS proof의 반복 stdout은 manifest가 소유한다.
- source 부재, source/stdout hash mismatch, line range 밖 quote, byte 불일치, duplicate finding-role, non-zero recorded exit, `exact_match=false``quote_gate` FAIL이다.
- manifest는 quote evidence 형식의 SSOT일 뿐이다. audit의 scope/matrix/finding/adversarial/priority/link/language/artifact gate와 기존 verdict 산식을 대체하거나 완화하지 않는다.
### 7.1 Proof hard gate
신규 report는 다음 기계 결과를 기록한다. 성공 proof의 shell stdout 전체를 본문에 반복하지 않는다.
```text
Manifest: <repo 또는 run namespace 안의 path>
Manifest SHA-256: <sha256>
Manifest schema: proof-manifest/v1
Proof: <N>
PASS: <N>
FAIL: 0
Runner exit: 0
Hard-gate exit: 0
```
controller는 `proof_hard_gate.py`에 동일 path·hash·count를 넘긴다. hard gate가 path confinement, persisted bytes hash, schema, proof/PASS/FAIL count와 source bytes 재검증을 모두 통과한 finding만 `P``G`에 포함한다. inline `sed`/`grep`은 디버깅 또는 대표 예시일 뿐 count SSOT가 아니다.
- `V` = manifest의 `proof_count`
- `P` = manifest의 `pass_count`
- `D` = runner가 manifest 발급 전에 제거한 proof 수
- `C` = line correction 수
- `G` = 필요한 proof role이 모두 PASS인 finding 수
- `U` = draft quote 수 `V`; `U > 0`이면 완료 판정 차단
### 7.2 실행한 검증 명령
본 섹션은 wiki 작업에 적용되는 자동 검증 명령을 기록한다. 코드(Java/Gradle) 빌드 명령은 본 rule 범위 밖이며, 그런 명령이 등장하면 본 보고서가 ca-tmpl 영역으로 잘못 진입한 것이므로 BLOCKED.
- 실행한 명령:
- `<command>` → <결과>
대표적인 wiki 검증 명령 예시:
```bash
# Frontmatter 필수 필드 카운트
grep -cE '^(title|source_type|status|tags|created):' '<file>'
# Parent 섹션 확인
grep -c '^## Parent' '<file>'
# 본문 wikilink 추출 후 존재 확인
grep -oE '\[\[[^]]+\]\]' '<file>' | sort -u
ls 'raw/...' 'wiki/...' # 각 대상에 대해
# Tag taxonomy 위반 검사
grep -h '^tags:' raw/**/*.md wiki/**/*.md | grep -oE '\[.*\]' | tr ',' '\n' | sort -u
```
- 실행하지 못한 명령과 이유:
- <command> — <reason>
- 본 응답에서 새로 작성된 wiki 파일 수: <N> / 수정된 파일 수: <M>
## 8. Generated Artifacts (분할 시에만)
- 전체 보고서: `docs/superpowers/specs/YYYY-MM-DD-<topic>-report.md>`
- 파일별 상세: `docs/superpowers/specs/YYYY-MM-DD-<topic>-per-file-findings.md>`
- 작성 일자: YYYY-MM-DD
- 작성 도구: Antigravity CLI / wiki-superpowers plugin
```
## Format Discipline
- **One file = one subsection in §4.** 파일을 묶지 않는다. 묶으면 누락이 보이지 않는다.
- **No "Pillar / Group / Theme" grouping in §4.** 그룹화는 §2 매트릭스 위쪽이나 §5에서만 허용. §4는 평면(flat) 파일별 구조 유지.
- **Every claim cites file:line.** 본문에 단정적 사실이 있는데 `<file:line>` 근거가 없으면 그 문장을 지우거나 `INFERENCE`로 라벨링한다.
- **Priority table only references analyzed files.** §5 행에 등장하는 파일은 §4에 반드시 하위섹션이 있어야 한다. 없으면 draft 폐기.
- **No mermaid/diagram filler.** 다이어그램은 본문 분석을 대체할 수 없다. 분석 없이 다이어그램만 있으면 `BLOCKED`.
- **No bilingual mirroring.** 한국어 본문과 영어 본문을 둘 다 쓰지 않는다. 사용자 언어 하나.
## Anti-Patterns to Avoid
| Pattern | Why it fails | Replacement |
| --- | --- | --- |
| "Pillar A: 4 files" + 묶음 비평 | 4개 중 어느 파일 어디서 나온 사실인지 추적 불가 | 파일당 §4 하위섹션 1개씩 |
| GitHub `[!WARNING]` admonition만 나열 | 출처가 사라짐. 인용 라인 없음 | `<file:line>` 인용 + 한 줄 발췌 |
| 영어 보고서 + 한국어 대화 | 사용자가 한 번 더 번역해야 함 | 사용자 언어로 통일 |
| Executive summary 없이 본론 바로 진입 | 사용자가 핵심을 알려면 끝까지 읽어야 함 | §1 한눈 요약 3~6 문장 |
| 우선순위 표에 정독하지 않은 파일 등장 | 추측을 권고로 둔갑 | §4에 있는 파일만 §5에 올림 |
| Verdict 없이 발견사항만 나열 | 사용자가 통과/실패 판단 불가 | 상단 frontmatter에 Verdict 명시 |
## Pre-Send Format Check
송신 직전, 에이전트는 자신의 draft에 대해 다음을 확인한다. 하나라도 실패하면 draft를 폐기하고 재작성한다.
1. 본문 산문 언어가 사용자 언어와 일치하는가?
2. §0 Source roots가 외부 디렉토리 참조 시 정의되어 있는가? 워크스페이스 내부만 다룬다면 "해당 없음 / N/A"이 명시되어 있는가?
3. §1~§7이 모두 존재하는가? (해당 없으면 명시적 "없음 / N/A")
4. §2 evidence matrix 행 수가 in-scope 파일 수와 일치하는가? 불일치면 §3에 reconciliation 블록이 있는가?
5. §4 파일별 하위섹션 수가 §2의 `READ_FULL` + `READ_PARTIAL` 행 수와 일치하는가?
6. §4의 각 finding이 **verbatim quote + 위치(file:line)** 를 Original goal과 Current state에 포함하는가?
7. §4의 각 finding이 **실무 가정 (Real-world assumptions)** 을 최소 1개, 각 가정에 무효 조건과 사용자 검증 방법을 포함하는가?
8. §4의 각 finding이 "이 finding이 무효해지는 경우" 명시를 포함하는가?
9. §5 우선순위 표의 모든 파일이 §4에 하위섹션을 가지고 있는가?
10. 본문의 모든 구체적 사실 주장이 verbatim quote + `<file:line>` 근거를 동반하는가? 단순 `(L67)` 형식 금지.
11. 모든 file:line 경로가 워크스페이스 상대 (또는 §0에 정의된 alias) 형식인가? 절대 경로 `/home/...` 금지.
12. 다이어그램/표가 분석을 대체하지 않고 보조만 하는가?
실패하면 사과로 채우지 않는다. 누락을 메우거나 명시적으로 `NOT_READ` 처리하고 다시 작성한다.
## No silent truncation (funnel 계약)
출력이 캡/슬라이스/top-N/skip 으로 coverage 를 bound 하면 **드롭한 수 + 이유**를 반드시 보고한다. funnel 은 균형해야 한다:
```
found = processed + dropped
```
- `found` = 식별한 총 항목. `processed` = 실제 판정한 수(결과 무관 — covered/missing/verified/promoted 모두 포함). `dropped` = 판정하지 않고 의도 제외(이유 필수).
- **agent 출력**은 `wiki-stats` 블록으로 보고한다(SubagentStop 이 균형·dropped_reason 검증 — `.claude/hooks/wiki_rules.py` `validate_stats_block`).
- **command 출력**은 `## Stats` 절로 보고한다.
- 침묵 누락은 "전부 다뤘다" 는 거짓 신호다 — 제3의 보고되지 않은 버킷을 두지 않는다.
@@ -0,0 +1,87 @@
# rules/subagent-input-contracts — 서브에이전트/명령 입력 계약
> `rules/` 의 방법론 규칙. controller(메인 에이전트 또는 `/branch-spec` 같은 오케스트레이터)가 **dispatch 전에 무엇을 모아야 하는가**를 agent별 form schema로 고정한다.
> 목적: agent 가 `NEEDS_CONTEXT` 로 멈추는 일을 줄이고 *되묻지 않는* 조립을 가능하게 한다.
> **SSOT 주의** — 각 agent 의 권위 있는 입력 정의는 그 agent 본문(`.claude/agents/<name>.md` 의 `## Required Inputs`)이다. 본 문서는 그것을 *재사용 가능한 체크 형태로 요약·참조*할 뿐, 값을 복제하지 않는다. 충돌 시 agent 본문이 우선.
## 원칙 (3-rule)
| Rule | 의미 |
|---|---|
| **C1. Pre-fill** | controller 는 dispatch 전에 아래 표의 *필수* 입력을 모두 채운다. 못 채우면 (a) 자동조사로 보강하거나 (b) 명시적 라벨(`UNSUPPORTED_DECISION` 등)로 남긴다 — 추측해서 FACT 로 채우지 않는다(CLAUDE.md §11). |
| **C2. Missing → 행동 명시** | 각 필수 입력에는 *누락 시 행동*이 정의돼 있다. "조용히 추측" 은 금지. `NEEDS_CONTEXT` / 자동조사 / 라벨 중 하나. |
| **C3. No SSOT 이중화** | 본 계약은 agent 본문을 참조만 한다. 입력 **(예: 허용 source_type 목록)은 agent 본문·`rules/naming-conventions.md`·`rules/tag-taxonomy.md` 에서 가져온다. |
## 입력 계약 표
표기: **필수** = dispatch 전 반드시 / 선택 = 있으면 사용 / *누락 시 행동* = 빈 채로 dispatch 됐을 때.
### `/branch-spec <slug>` (오케스트레이터 명령)
| 입력 | 구분 | 누락 시 행동 |
|---|---|---|
| `branch_slug` | 필수 | 인자 비면 사용자에게 요청(종료) |
| 대상 노트 존재 (`raw/branch-notes/<slug>.md`) | 필수(전제) | 없으면 `/branch` 먼저 안내(종료) |
| `parent` (project 또는 parent branch) | 필수 | 노트의 `## Parent` 에서 읽음. 없으면 `NEEDS_CONTEXT` |
| `sources[]` (외부 자료 URL 또는 `[[raw/...]]`) | 조립 입력 | URL → `wiki-source-summarizer` dispatch. 하나도 없으면 결정마다 자동조사(아래) |
| `decision_candidates[]` | 조립 입력 | source Claim 에서 자동 도출 시도 |
| `scope.in[]` / `scope.out[]` | 조립 입력 | 비면 in-scope 만 채우고 out 은 빈 채로 `Should-fix` 보고 |
자동조사 bound: 근거 없는 결정 회당 최대 **6개** 까지 `wiki-decision-researcher` dispatch. 초과분은 `deferred` 로 보고(silent 절단 금지). 조사 후에도 근거 없으면 `UNSUPPORTED_DECISION` + trade-off 한 줄.
### `/project-spec <slug> <목표> [근거 URL ...]` (오케스트레이터 명령)
project-note hub 를 ca-skeleton caliber 로 채우고 끝에 readiness 게이트([[rules/project-readiness-gate]]). `/branch-spec` 의 hub 짝.
| 입력 | 구분 | 누락 시 행동 |
|---|---|---|
| `project_slug` | 필수 | 인자 비면 사용자에게 요청(종료 — 대상 파일 모름) |
| 대상 노트 존재 (`raw/project-notes/<slug>.md`) | 필수(전제) | 없으면 `/project` 먼저 안내(종료) |
| `goal` (프로젝트 목표 prose) | 필수 | **종료 말고** `AskUserQuestion` 으로 물어 받아 진행 |
| `owner_decisions[]` (범위/우선순위/성공기준 임계) | 사용자 소유 | 추측·`UNSUPPORTED` 금지 — `AskUserQuestion`(하네스 내장 툴) 으로 직접 질의 |
| `sources[]` (URL) | 조립 입력 | hub 결정 근거는 `wiki-source-summarizer`(parent = `[[raw/project-notes/<slug>]]`) dispatch |
직접 dispatch: **`wiki-source-summarizer`**(§5 hub 소싱) + **`project-readiness-auditor`**(§9 게이트) 둘뿐. `wiki-decision-researcher`(결정별 깊은 대안조사)는 `parent_branch` 계약상 **branch 단계로 이관**`/project-spec` 에서 안 부른다. `wiki-diagram-reviewer`(≥95)는 사용자가 별도 실행(게이트 강제 아님). 자동소싱 bound 6개·초과분 `deferred`(R3 면제).
차이(`/branch-spec` 대비): ① 사용자 소유 결정은 `UNSUPPORTED` 라벨이 아니라 `AskUserQuestion`(hub in-the-loop), ② 게이트는 readiness(R1~R4) 단일, ③ 사용자 행동으로만 해소되는 Blocking(다이어그램·소유결정)은 `Ready-pending-user` 로 종료(무한루프 금지).
### `wiki-source-summarizer`
권위: `.claude/agents/wiki-source-summarizer.md``## Required Inputs` (링크 아님 — Obsidian 은 `.claude/` 를 색인하지 않으므로 백틱 코드로만 표기). 요약:
| 입력 | 구분 | 누락 시 행동 |
|---|---|---|
| `url` | 필수 | `NEEDS_CONTEXT` |
| `source_type` (`official-doc` \| `company-tech-blog`) | 필수 | 다른 값이면 reject |
| `parent` + 이 자료가 정당화하는 결정(한 줄) | 필수 | `NEEDS_CONTEXT` |
| `claim_id_prefix` / `file_slug` / `vendor` | 선택 | slug·URL 에서 도출 |
### `wiki-decision-researcher`
| 입력 | 구분 | 누락 시 행동 |
|---|---|---|
| `decision_topic` | 필수 | `NEEDS_CONTEXT` |
| `parent_branch` | 필수 | `NEEDS_CONTEXT` |
| `constraints` (선택 조건/요구사항) | 필수 | 비면 일반 비교만 — `Should-fix` 보고 |
| `N` (대안 개수) | 선택 | 기본 3 |
### `wiki-doc-author`
권위: `.claude/agents/wiki-doc-author.md``## Required Inputs`. 요약:
| 입력 | 구분 | 누락 시 행동 |
|---|---|---|
| `mode` (`create` \| `migrate`) | 필수 | controller 에 reduction 요청 |
| `category` | 필수 | `NEEDS_CONTEXT` |
| `title` | 필수 | `NEEDS_CONTEXT` |
| `parent` (daily-note·project-note 제외) | 필수 | 추정 금지 — `NEEDS_CONTEXT` |
| `file_slug` | 선택 | title 에서 도출(create) |
| branch-note 의 `sources[]` + `claim_evidence` | 필수(branch-note) | 없으면 `NEEDS_CONTEXT` 또는 `UNSUPPORTED_DECISION` 라벨 |
## 명명된 실패 모드
- `UNFILLED_REQUIRED_INPUT` (C1): 필수 입력이 비었는데 자동조사·라벨 중 어느 것도 적용 안 됨.
- `SILENT_GUESS` (C1): 근거 없는 값을 추측해 FACT 로 채움 — 금지.
- `MISSING_FALLBACK_ACTION` (C2): 입력 누락에 대한 행동이 정의되지 않음.
- `SSOT_DUPLICATION` (C3): 입력 값을 agent 본문에서 참조하지 않고 본 계약에 복제 — drift 위험.
- `UNBOUNDED_RESEARCH` (`/branch-spec`): 자동조사가 bound 없이 확장.
File diff suppressed because one or more lines are too long
+116
View File
@@ -0,0 +1,116 @@
---
title:
source_type: blog
status: draft
confidence: unknown
tags: [blog]
related_projects: []
last_reviewed:
canonical_sources: []
audience: backend-engineer
target_publish:
status_label: outline
---
# {{title}}
> Layer: `wiki/blog/` — **외부 공개용 블로그 글 초안·완성본**. canonical (`wiki/concepts/` + `wiki/projects/`) 에서 파생된 산출물.
> 상태: draft → reviewed → verified → **published-ready** (외부 게시 가능)
> `status_label`: `outline` | `drafting` | `review` | `ready` | `published` | `retired`
> `audience`: `backend-engineer` | `senior-engineer` | `tech-lead` | `general` — 깊이·전문용어 사용량이 달라짐.
## 부모 (필수)
> wiki/blog/ 는 derived layer. **반드시 canonical wiki/concepts/ 또는 wiki/projects/ 에서 파생.** raw 또는 branch에서 직접 파생 금지.
- 핵심 canonical (최소 1개+):
- `[[wiki/concepts/<...>]]` — <어떤 개념을 다루는지>
- `[[wiki/projects/<...>]]` — <어떤 프로젝트 사실을 다루는지>
- 영감 출처 (선택):
- `[[raw/blog-topics/<...>]]` — <어떤 raw 글감이 출발점이었나>
- `[[raw/job-postings/<...>]]` — <어떤 공고가 글감을 자극했나>
- `[[raw/interviews/<...>]]` — <어떤 면접 질문에서 파생>
## 타깃 독자
> 이 글을 누가 읽을 것인지. 톤·전문용어·깊이가 결정됨.
- 독자 profile:
- 독자가 이미 알고 있을 것이라 가정하는 것:
- 독자가 처음 듣는다고 가정하는 것:
## 도입
> 왜 이 글을 쓰는가. 독자에게 이 글의 가치를 1~2문장으로.
- 문제 / 궁금증:
- 이 글이 답하는 것:
- 이 글이 답하지 않는 것 (스코프):
## 본문 outline
> 글의 흐름. 초안 단계에서는 outline 만, drafting 단계부터 본문.
1. <섹션 1 제목> — <핵심 메시지 한 줄>
2. <섹션 2 제목> — <핵심 메시지 한 줄>
3. <섹션 3 제목> — <핵심 메시지 한 줄>
## 본문
> drafting 단계에서 채움. 모든 사실 주장은 canonical 인용으로 뒷받침.
(여기에 글 본문)
## 코드 예제
> 가능한 실제 프로젝트 코드 인용. 가짜 예제 금지. 추출 시 출처 PR·커밋 명시.
```<lang>
// 출처: [[wiki/projects/<...>]] — <commit-sha>
<code>
```
## 근거 (canonical 인용 필수, derived layer 의무)
> 모든 사실 주장은 canonical 또는 raw 인용으로 뒷받침. 자기 추론은 명시적으로 "내 해석" 으로 분리.
- `[[wiki/concepts/<...>]]` — <어떤 사실의 출처>
- `[[wiki/projects/<...>]]` — <어떤 결정의 출처>
- `[[raw/official-docs/<...>]]` — <인용한 공식 자료>
- `[[raw/company-tech-blogs/<...>]]` — <인용한 사례>
## 사실 vs 의견
> 독자가 자신 있게 인용할 수 있도록.
- **사실 (검증됨)**:
- <항목> — 근거: `[[wiki/...]]` 또는 `[[raw/...]]`
- **내 해석·의견 (검증 안 된 추론)**:
- <항목> — "내 경험상" / "내 해석으로는" 같은 표현으로 명시
- **알지 못하는 것**:
- <항목> — "이 부분은 다음 글에서 다루겠다" 또는 솔직히 표기
## 답할 수 있는 범위
> 이 글을 읽은 사람에게 후속 질문을 받았을 때 자신 있게 답할 수 있는 범위.
- 자신 있게 답할 수 있는 후속 질문:
- "그건 다음 글에서 다루겠다" 라고 해야 하는 부분:
## 게시 체크리스트
`ready` → `published` 로 올리기 전 확인.
- [ ] 모든 사실 주장에 canonical 링크 있음
- [ ] 사실 vs 의견 분리 명시됨
- [ ] 과장 단어 (`완벽`, `극한`, `100%`, `최고`, `역사상 가장`) 없음
- [ ] 코드 예제 출처 명시
- [ ] 타깃 독자 가정과 톤 일치
- [ ] `/lint` 통과
- [ ] 게시 URL 기록 (게시 후):
## 관련
- 후속 글 후보: `[[wiki/blog/<...>]]`
- 관련 포트폴리오 항목: `[[wiki/portfolio/<...>]]`
- 영감을 받은 raw 자료: `[[raw/blog-topics/<...>]]`, `[[raw/job-postings/<...>]]`, `[[raw/lectures/<...>]]`
@@ -0,0 +1,110 @@
---
title: blog-topic / {{short-topic-slug}}
source_type: blog-topic
status: raw
related_branches: []
related_projects: []
tags: [blog-topic, {{project-slug}}] # L2 프로젝트 슬러그 필수 (tag-taxonomy.md §2). L3~L5 는 주제별 추가.
created: YYYY-MM-DD
status_label: captured
target_audience: backend-engineer
inspiration_url: # 외부 자료에서 영감 받았으면 원본 URL. 없으면 빈 채로.
archive_url: # inspiration_url 의 Wayback Machine 등 archive snapshot. CLAUDE.md §7.
---
# blog-topic: {{short-topic-slug}}
> Layer: `raw/blog-topics/` — 채용공고가 아닌 작업·학습·트러블슈팅에서 나온 **블로그 글감 원석**. 다듬어진 블로그 초안은 canonical (`wiki/concepts/` 또는 `wiki/projects/`) 정제 후 `/blogify` 또는 수동 작성으로 `wiki/blog/`에 별도 작성한다. 원본은 raw에 영구 보관.
> `status_label`: `captured` | `expanded` | `ready-for-canonical` | `derived-to-blog` | `parked`
> **Citation discipline (필수)**:
>
> - `## 핵심 주장 후보` 의 각 사실/경험 후보는 단순 `[[branch-note]]` 링크만으로는 부족하다. 다음 셋 중 하나를 동반한다:
> 1. branch-note 의 **Decision ID** (예: "근거: `feature-X.md` D3").
> 2. 외부 source 의 **claim ID** (예: `AT-TX-C5`, `UNIL-TX-C1`) — 가능하면 raw source 파일의 anchor 인용 (`<path>.md#AT-TX-C5`).
> 3. branch-note 의 **section + line ref** (예: `feature-X.md §결정 사항`, `feature-X.md:104`).
> - 외부 자료에 다수파 vs 소수파 trade-off 가 있다면 명시 (`다수파: @Transactional 직접 부착`, `소수파: TransactionPort 추상화` 등).
> - `## Outline seed` 의 각 섹션 후보는 `→ 핵심 메시지 한 줄` 으로 다음 글의 단락 핵심을 미리 적는다. 단순 섹션 제목만 두지 않는다.
> - `## Canonical 전환 후보` 는 추상 후보가 아니라 **구체 파일명** 까지 명시 (`wiki/projects/ca-tmpl/<topic>.md`).
> - `## 미해결 / Unknown` 의 "과장하면 안 되는 부분" 은 반드시 한 줄 이상 채운다 — local-verified / prod-verified / documented-only 의 등급을 흐리지 말 것.
## 부모
> 이 글감이 어느 작업·프로젝트에서 나왔는지 명시. **최소 1개 필수.** 일반 주제면 `[[raw/project-notes/<project>]]` 로 연결.
- `[[raw/branch-notes/{{branch-name}}]]` — <왜 이 branch에서 이 글감이 나왔는지 한 줄>
- (또는) `[[raw/project-notes/{{project-name}}]]`
## 트리거
> 어떤 사건에서 이 글감이 나왔는지 구조적으로 기록. `/lint` / `/query` 에서 trigger 유형별 필터링 가능.
- 트리거 유형: `branch-work` | `error` | `interview` | `lecture` | `conversation` | `other`
- 트리거 날짜: YYYY-MM-DD
- 트리거 연결 노트: `[[raw/branch-notes/...]]` 또는 `[[raw/errors/...]]` 또는 `[[raw/lectures/...]]` 또는 `[[raw/interviews/...]]`
## 글감
- 한 문장 요지:
- 예상 제목 후보:
- <제목 후보 1>
- <제목 후보 2>
> 타깃 독자는 frontmatter `target_audience:` 필드를 SSOT 로 사용 (중복 방지).
## 핵심 주장 후보
> 아직 canonical이 아니다. 사실/경험/의견 후보를 분리한다.
- 사실 후보:
- <검증 가능한 사실> — 근거 후보: `[[raw/branch-notes/<...>]]`
- 경험 후보:
- <내가 직접 한 작업/검증> — 근거 후보: `[[raw/branch-notes/<...>]]`
- 의견/해석 후보:
- <내 해석 또는 글의 관점>
## Outline seed
1. <섹션 후보 1> — <핵심 메시지>
2. <섹션 후보 2> — <핵심 메시지>
3. <섹션 후보 3> — <핵심 메시지>
## Canonical 전환 후보 / Canonical extraction candidates
> `wiki/blog/`로 바로 가지 않는다. 먼저 어떤 canonical 문서로 정제할지 기록한다.
- `wiki/projects/<project>/<topic>.md` 후보:
- <프로젝트 적용 사실로 승격할 항목>
- `wiki/concepts/<concept>.md` 후보:
- <일반 개념으로 승격할 항목>
- 필요한 추가 검증:
- <테스트 / 공식문서 확인 / 코드 링크 / 리뷰>
## 근거 후보
> 글감 단계의 후보 링크다. 최종 blog의 사실 근거는 canonical 문서에서 다시 검증한다.
- `[[raw/branch-notes/<...>]]` — <어떤 경험/결정의 근거인지>
- `[[raw/errors/<...>]]` — <관련 트러블슈팅이 있다면>
- `[[raw/interviews/<...>]]` — <관련 예상 질문이 있다면>
- `[[raw/official-docs/<...>]]` — <공식 근거 후보>
- `[[raw/company-tech-blogs/<...>]]` — <사례 근거 후보>
## 미해결
- 아직 확인해야 할 사실:
- 과장하면 안 되는 부분:
- 블로그로 쓰기 전에 필요한 canonical 정제:
## 처리 결정
- 액션: `keep-as-topic` | `expand` | `promote-to-canonical` | `derive-to-blog` | `park`
- 이유:
- 다음 단계:
## 관련
- 관련 branch: `[[raw/branch-notes/{{branch-name}}]]`
- 관련 error: `[[raw/errors/<...>]]` (있다면)
- 관련 interview prep: `[[raw/interviews/<...>]]` (있다면)
- derived blog: 생성 전. 생성 시 `wiki/blog/<slug>-YYYY-MM-DD.md` 후보
@@ -0,0 +1,473 @@
---
title: branch / {{branch-name}}
source_type: branch-note
status: raw
id: {{branch-id}}
kind: {{project-work-item|branch-child|standalone}}
project: {{project-name}}
work_item: {{WI-PROJECT-NNN}}
inherits: [{{DEC-PROJECT-DOMAIN-NNN@revision}}]
refines: []
overrides: []
depends_on: []
imports: []
delegates: []
accepts_delegations: []
contract_packet: 1
branch: {{branch-name}}
parent_branch:
related_projects: []
tags: [branch]
created: YYYY-MM-DD
target_merge:
status_label: in-progress
---
# branch: {{branch-name}}
> Layer: `raw/branch-notes/` — 단일 브랜치의 **TODO·결정·진행 기록**. 머지/종료 후 verified 결과는 `/ingest`로 `wiki/projects/`에 추출. 원본은 raw에 영구 보관.
> `status_label`: `in-progress` | `review` | `merged` | `abandoned`
> `id`: project 직접 자식은 `WI-`를 `BR-`로 치환한 stable ID, child는 결정론적으로 생성한 `BR-<PROJECT>-CHILD-<HASH>`를 사용한다. 파일명 slug를 ID로 재사용하지 않는다.
> `contract_packet`: branch contract packet schema revision. 현재 v2 작성값은 양의 정수 `1`.
> **계층 표기**: "root branch" 라는 별도 개념은 없음. project 의 직접 자식 branch 는 `parent_branch:` 를 **비워두고** `related_projects` 만 채움. 다른 branch 의 자식이면 `parent_branch: <부모 branch 이름>` 명시 + `## Parent` 섹션의 부모 wikilink 필수.
<!-- section-id: branch-parent -->
## 부모 (필수)
> 이 branch 가 어느 작업 묶음에 속하는지. 모든 branch 는 예외 없이 upward link 보유.
다음 중 정확히 하나:
- **Project 의 직접 자식 branch** (`parent_branch:` 비어있음): `[[raw/project-notes/{{project-name}}]]` 만 명시
- **다른 branch 의 자식** (`parent_branch:` 채워짐): `[[raw/branch-notes/{{parent-branch}}]]` 명시 + `frontmatter.parent_branch` 와 일치
선택 (있을 때):
- 형제 branch (같은 부모의 다른 자식):
- `[[raw/branch-notes/{{sibling-1}}]]`
- `[[raw/branch-notes/{{sibling-2}}]]`
<!-- section-id: branch-contract-packet -->
## 브랜치 계약 패킷
> project Work Item 에서 내려온 실행 계약의 snapshot. `project`·`work_item`·`inherits`·`depends_on` 은 project registry row 와 일치해야 한다.
> project 결정의 owner 는 project-note 다. 여기에는 **pinned pointer + 1줄 요약 + branch 적용점**만 쓰고 임계값·메커니즘·예외 목록 같은 상세를 복제하지 않는다.
- **생성 시 프로젝트 개정**: `{{positive-project-revision}}`
- **패킷 스키마**: `contract_packet: 1`
- **완료 조건**: <실행계획의 완료 조건을 그대로 연결>
<!-- section-id: inherited-project-decisions -->
### 상속한 프로젝트 결정
| Decision Ref | Project Summary | Branch Application | Source |
|---|---|---|---|
| `DEC-<PROJECT>-<DOMAIN>-001@1` | <project registry 의 1줄 요약> | <이 branch 가 consume 하는 경계> | `[[raw/project-notes/<project>]]` |
<!-- section-id: branch-local-decisions -->
### 브랜치 지역 결정
> 상세 근거와 선택 조건은 아래 `## 결정-근거 매핑`의 동일 D-row가 소유한다. `Relation` 은 `local` 또는 `refines DEC-...@revision`.
| Decision ID | Decision | Relation | Supporting Claims | Status |
|---|---|---|---|---|
| D1 | <branch-local 결정 1줄 요약> | `local` | `raw/official-docs/<slug>.md#C1` | `proposed` |
<!-- section-id: declared-overrides -->
### 선언한 예외
> inherited project decision 과 다른 동작이 필요할 때만 작성한다. frontmatter `overrides` 와 동일한 pinned ref 를 사용하며 이유·승인·상태를 남긴다.
| Override ID | Overrides | Reason | Approval | Status |
|---|---|---|---|---|
| O1 | `DEC-<PROJECT>-<DOMAIN>-001@1` | <project 기본값을 적용할 수 없는 조건> | `needs-approval` | `proposed` |
<!-- GENERATED: artifact-imports:start -->
### 가져온 artifact 계약
| Artifact Ref | Owner | Producer | Schema Ref |
|---|---|---|---|
<!-- GENERATED: artifact-imports:end -->
<!-- GENERATED: project-contract-imports:start -->
## 가져온 프로젝트 계약
| Ref | Owner | 요약 | Branch 적용 |
|---|---|---|---|
<!-- GENERATED: project-contract-imports:end -->
<!-- GENERATED: received-delegations:start -->
### 수신한 위임
| Delegation Ref | From | Concern | Status |
|---|---|---|---|
<!-- GENERATED: received-delegations:end -->
<!-- GENERATED: flow:start -->
### 가져온 흐름 단계
| Stage Ref | Order | Owner | Input | Action | Output |
|---|---:|---|---|---|---|
<!-- GENERATED: flow:end -->
<!-- section-id: branch-goal -->
## 목표
이 브랜치에서 해결하려는 문제. 관련 이슈 / PR 링크.
- 이슈:
- PR:
<!-- section-id: branch-scope -->
## 범위
### 포함 범위
- 항목 1
- 항목 2
### 제외 범위
> 의도적으로 제외한 것. 면접 등에서 "이건 범위에 없었습니다"라고 답할 근거.
- 항목 1
## 근거 (필수, 최소 1개+)
> 이 branch의 구현·설계 결정의 **근거가 되는 외부 자료**. 공식 문서·대기업 기술 블로그·강의 등 raw 자료를 인용. 같은 자료가 여러 결정의 근거면 결정 표시와 함께 여러 번 등장 가능.
| Source | 정당화하는 결정 |
|---|---|
| `[[raw/official-docs/<...>]]` | <어떤 결정의 근거인지 한 줄> |
| `[[raw/company-tech-blogs/<...>]]` | <한 줄> |
| `[[raw/lectures/<...>]]` | <한 줄> |
근거 자료가 raw에 아직 없다면 먼저 `raw-source-template` 또는 `lecture-note-template` 으로 raw에 등록한 뒤 여기서 링크.
## TODO
각 항목 옆에 증거 등급 표기: `actually-implemented` | `locally-verified` | `prod-verified` | `documented-only` | `planned` | `needs-confirmation`
- [ ] 작업 1 — 등급: `planned`
- [ ] 작업 2 — 등급: `planned`
- [x] 작업 3 — 등급: `actually-implemented`
## 진행 중 메모
작업하며 떠오른 메모. 자유 형식.
## 결정 사항
> 추후 면접/회고에서 "왜 이렇게 했나" 답할 근거. 대안과 함께 기록. 각 결정의 근거는 위 Sources 또는 새로 추가된 raw 자료를 가리킬 것.
- YYYY-MM-DD: <결정 내용> / 이유: <왜> / 검토한 대안: <대안> / 근거: `[[raw/official-docs/<...>]]`
<!-- section-id: decision-evidence -->
## 결정-근거 매핑
> 각 결정이 어떤 raw source claim 으로 뒷받침되는지 명시한다.
> `Decision ID` 는 이 branch-note 안에서 안정적으로 유지한다. 예: `D1`, `D2`.
> `Supporting Claims` 는 `raw/<category>/<slug>.md#C1` 형식으로 연결한다.
> `선택 조건` 열(R2): "이 조건일 때 이 결정, 다른 조건이면 어떤 대안". 분기 없으면 `N/A`.
| Decision ID | Decision | 선택 조건 (언제 이 결정 / 언제 대안) | Supporting Claims | Evidence Strength | Open Risk |
|---|---|---|---|---|---|
| D1 | <결정 내용> | <이 조건일 때 이 결정, 다른 조건이면 어떤 대안> | `raw/official-docs/<slug>.md#C1`, `raw/company-tech-blogs/<slug>.md#C2` | `official-vendor-doc + company-case-study` | <아직 검증해야 할 위험> |
| D2 | <결정 내용> | <선택 조건 또는 N/A> | `raw/official-docs/<slug>.md#C3` | `official-standard` | <위험 또는 N/A> |
<!-- section-id: implementation -->
## 구현 가이드
> *결정 (Decisions)* 이 "*무엇* 을 할 것인가" 라면, 본 §는 "*어디에 어떻게* 구현될 것인가" 의 사전 명세 — *문서가 모호해서 구현자가 임의로 정해야 했던 결정* 카탈로그. 작성 목표는 다음 구현자가 *되묻지 않아도 코드를 작성할 수 있는 수준*.
>
> **본 §는 일률적 anchor list 를 강제하지 않는다.** branch 마다 구현 내용·범위가 다르므로 sub-section 은 *이 branch 의 결정과 근거에서 도출되는 것만* 작성. 어떤 branch 는 error mapping 표 + 정적 강제 카탈로그, 어떤 branch 는 migration 단계 + wiring, 어떤 branch 는 sequence + state machine. 형식 예시는 `[[raw/branch-notes/feature-boundary-validation-mapping-contract]]` 의 §구현 가이드 참조.
>
> **3-rule meta principle (필수 준수)**:
>
> 1. **R1. Reference 필수** — 각 sub-section / row / cell 은 본 branch 의 `Decision ID` (예: D1, D2) + 그 결정의 `Supporting Claim ID` (예: `RAW-SLUG-C1`) 를 reference. *근거 없는 결정 금지* — 모든 구현 detail 은 결정 + 근거의 *도출* 이어야 함.
> 2. **R2. UNSUPPORTED_IMPL_DECISION 명시** — 근거 raw 가 *원칙* 만 권고하고 *detail* (메커니즘 선택 / 클래스/rule 명명 / glob 패턴 / algorithm / factory API 모양 등) 은 권고하지 않는 cell 은 `UNSUPPORTED_IMPL_DECISION` 라벨 + 사용자 trade-off 근거 한 줄. 이게 *근거 있는 결정 vs 사용자 임의 trade-off* 의 경계.
> 3. **R3. OUT_OF_BRANCH_SCOPE 정제** — 본 branch 결정 범위 밖 cell 은 §구현 가이드에 *남기지 않음*. 별도 branch 또는 canonical SSOT 로 이관 (이관 history 는 별도 § "Audit & Findings" 등에 보존). 도메인 특화 detail (ca-tmpl skeleton 범위 밖) 도 동일하게 정제.
>
> **각 sub-section 의 권장 헤더 패턴**:
>
> ```markdown
> ### N. <sub-section 제목>
>
> > **Trace**: <In-scope row 들 + Decision ID + Supporting Claim ID 의 매핑 (한 줄/한 단락)>
> >
> > - **UNSUPPORTED_IMPL_DECISION**: <근거 없는 사용자 임의 결정 항목들 + 각각의 trade-off 근거 한 줄>
>
> <표 또는 명확한 구조 — 자유 텍스트 = 모호함 = 되묻기 원인>
> ```
### 1. <sub-section 제목 — 본 branch 의 결정 영역 안에서만>
> **Trace**: <Decision ID + Supporting Claim ID 매핑>
>
> - **UNSUPPORTED_IMPL_DECISION**: <임의 결정 항목 + trade-off 한 줄>
(표 / 명세 / 카탈로그 / 절차 — 본 branch 의 결정 도출 detail)
### 2. ... (필요 시 추가)
<!-- section-id: edge-failure-dependency -->
## 엣지·실패·의존
> R4(깊이 게이트) 캡처용. 정상 경로 외에 *구현 중 부딪힐* 실패/엣지/다른 계약 의존을 미리 열거. 없으면 "해당 없음" 명시(공란 금지).
- **실패·엣지 경로**: <입력 경계 / 타임아웃 / 부분 실패 / 동시성 등 — 각 경로의 기대 동작>
- **다른 계약 의존**: `[[raw/branch-notes/<other-branch>]]``D<n>` 에 의존 — <무엇을 consume 하는지, 그 계약이 바뀌면 본 브랜치 영향>
<!-- section-id: claims-to-verify -->
## 검증해야 할 주장
> 공식 문서나 사례는 근거지만, 내 프로젝트에서의 동작을 자동으로 보장하지 않는다.
> 구현 전/중/후에 실제로 검증해야 하는 주장을 분리한다.
| Claim | Why uncertain | How to verify | Status |
|---|---|---|---|
| <검증할 주장> | <불확실한 이유> | <테스트/grep/실행 검증 방법> | `needs-confirmation` |
| <검증할 주장> | <이유> | <방법> | `planned` |
## 관심사 커버리지 (coverage-auditor 자동 생성 — 있을 때)
> `/coverage` 가 채우는 **생성물** — 손으로 유지하지 않는다. governing 문서(frontmatter `governing_docs`)가 요구하는 관심사를 이 브랜치가 빠짐없이 덮는지의 결과. 기준: `rules/coverage-gate.md`.
> 상태: `covered-here`(이 브랜치 결정) / `delegated`(다른 owner 브랜치) / `missing`(아무도 안 맡음 → Blocking).
| 관심사 | 상태 | owner | 심각도 | 근거 |
|--------|------|-------|--------|------|
| <governing doc 의 관심사> | covered-here | — | — | D<n> |
| <관심사> | delegated | feature-<owner> | OK/Should-fix | §Audit 위임 링크 |
| <관심사> | missing | (없음) | 🔴 Blocking | governing doc §<x> 요구, 결정 없음 |
## 마주친 문제
> 짧은 메모만. 깊이 있는 트러블슈팅은 `raw/errors/` 로 분리하고 아래 Cluster에 연결.
- 이슈 1
- 원인:
- 시도:
- 해결: (또는 미해결이면 `needs-confirmation`)
- 별도 에러 노트로 분리됨: `[[raw/errors/<...>]]` (생성 시)
## 묶음 (이 branch에서 파생된 자료)
> 이 branch는 단일 노트가 아니라 **작업 묶음의 entry point**. 이 branch에서 파생된 모든 raw 노트를 카테고리별로 명시. 자식 노트가 forward link만 박아도 Obsidian backlink로 자동 발견되지만, 읽기 흐름과 분류를 위해 hub가 명시적으로 그룹화한다.
### Sub-branches (세부 작업)
- `[[raw/branch-notes/<sub-branch-1>]]` — <한 줄 요약>
- `[[raw/branch-notes/<sub-branch-2>]]` — <한 줄 요약>
### 오류 기록 (이 branch 작업 중 발생)
- `[[raw/errors/<...>]]` — <한 줄 요약>
### 면접 준비 (이 작업에서 나올 수 있는 면접 질문)
- `[[raw/interviews/<...>]]` — <한 줄 요약>
### 강의 (이 작업을 위해 학습한 강의)
- `[[raw/lectures/<...>]]` — <한 줄 요약>
### job-posting tie-ins (이 작업에서 파생된 글감)
- `[[raw/blog-topics/<...>]]` — <채용공고가 아닌 작업·학습·트러블슈팅 기반 글감 후보>
- `[[raw/job-postings/<...>]]` — <채용공고에서 파생된 글감 후보>
- derived blog: 생성 전. 생성 시 `wiki/blog/<slug>-YYYY-MM-DD.md` 후보
## 관련 일일 노트
> 이 브랜치를 작업한 날짜들. 양방향 nav 유지.
- `[[raw/daily-notes/YYYY-MM-DD]]`
- `[[raw/daily-notes/YYYY-MM-DD]]`
## 완료 후 정리
> 머지/종료 시점에 채움. `/ingest`가 이 섹션을 기준으로 wiki/projects/에 추출.
- PR 링크:
- 리뷰 메모:
- 머지 결과 / 배포 환경: (로컬/dev/staging/prod 어디까지 검증됐는지)
- **wiki 추출 대상** (verified만, `wiki/projects/`로만 추출):
- `actually-implemented` 항목:
- `locally-verified` 항목:
- `prod-verified` 항목:
- **추출하지 않을 항목** (planned / documented-only / abandoned):
<!--
아래 region은 `branch_from_project.py`의 결정론 renderer가 소비한다.
사람이 복사하는 위 안내 template과 달리, 모든 값은 Work Item registry에서 주입되며
`branch-contract` generated region은 runtime 외 작성자가 수정할 수 없다.
-->
<!-- RUNTIME-TEMPLATE: branch-from-project:start -->
---
title: branch / {{branch_slug}}
source_type: branch-note
status: raw
id: {{branch_id}}
kind: project-work-item
project: {{project}}
work_item: {{work_item}}
inherits: {{inherits_yaml}}
refines: []
overrides: []
depends_on: {{depends_on_yaml}}
imports: []
delegates: []
accepts_delegations: []
contract_packet: 1
contract_packet_sha256: {{contract_packet_sha256}}
branch: {{branch_slug}}
parent_branch:
related_projects: [{{project}}]
tags: [branch]
created: {{created}}
target_merge:
status_label: in-progress
---
# branch: {{branch_slug}}
<!-- section-id: branch-parent -->
## 부모 (필수)
{{project_parent_link}}
<!-- GENERATED: branch-contract:start -->
<!-- section-id: branch-contract-packet -->
## 브랜치 계약 패킷
- **생성 시 프로젝트 개정**: `{{project_revision}}`
- **패킷 스키마**: `contract_packet: 1`
- **완료 조건**: {{completion}}
<!-- section-id: inherited-project-decisions -->
### 상속한 프로젝트 결정
| Decision Ref | Project Summary | Branch Application | Source |
|---|---|---|---|
{{inherited_rows}}
<!-- section-id: branch-local-decisions -->
### 브랜치 지역 결정
| Decision ID | Decision | Relation | Supporting Claims | Status |
|---|---|---|---|---|
<!-- section-id: declared-overrides -->
### 선언한 예외
| Override ID | Overrides | Reason | Approval | Status |
|---|---|---|---|---|
<!-- GENERATED: branch-contract:end -->
<!-- GENERATED: artifact-imports:start -->
### 가져온 artifact 계약
| Artifact Ref | Owner | Producer | Schema Ref |
|---|---|---|---|
<!-- GENERATED: artifact-imports:end -->
<!-- GENERATED: project-contract-imports:start -->
## 가져온 프로젝트 계약
| Ref | Owner | 요약 | Branch 적용 |
|---|---|---|---|
<!-- GENERATED: project-contract-imports:end -->
<!-- GENERATED: received-delegations:start -->
### 수신한 위임
| Delegation Ref | From | Concern | Status |
|---|---|---|---|
<!-- GENERATED: received-delegations:end -->
<!-- GENERATED: flow:start -->
### 가져온 흐름 단계
| Stage Ref | Order | Owner | Input | Action | Output |
|---|---:|---|---|---|---|
<!-- GENERATED: flow:end -->
<!-- section-id: branch-goal -->
## 목표
- `{{work_item}}`의 완료 조건을 구현한다: {{completion}}
<!-- section-id: branch-scope -->
## 범위
### 포함 범위
- Work Item 완료 조건
### 제외 범위
- project decision registry 변경
## 근거 (필수, 최소 1개+)
외부 근거 미등록. `/branch-spec {{branch_slug}}` 단계에서 source claim을 연결한다.
## TODO
- [ ] {{completion}} — 등급: `planned`
## 진행 중 메모
아직 없음.
## 결정 사항
project 결정 외 branch-local 결정은 아직 없음.
<!-- section-id: decision-evidence -->
## 결정-근거 매핑
| Decision ID | Decision | 선택 조건 (언제 이 결정 / 언제 대안) | Supporting Claims | Evidence Strength | Open Risk |
|---|---|---|---|---|---|
<!-- section-id: implementation -->
## 구현 가이드
`/branch-spec` 단계에서 source claim 기반으로 작성한다.
<!-- section-id: edge-failure-dependency -->
## 엣지·실패·의존
- **실패·엣지 경로**: `/branch-spec` 단계에서 구체화한다.
- **다른 계약 의존**: {{dependency_display}}
<!-- section-id: claims-to-verify -->
## 검증해야 할 주장
| Claim | Why uncertain | How to verify | Status |
|---|---|---|---|
## 관심사 커버리지 (coverage-auditor 자동 생성 — 있을 때)
`/coverage` 실행 전.
## 마주친 문제
아직 없음.
## 묶음 (이 branch에서 파생된 자료)
<!-- GENERATED: branches:start -->
<!-- GENERATED: branches:end -->
## 관련 일일 노트
해당 없음.
## 완료 후 정리
- PR 링크:
- 리뷰 메모:
<!-- RUNTIME-TEMPLATE: branch-from-project:end -->
@@ -0,0 +1,387 @@
---
title: ""
source_type: "report"
status: "draft"
confidence: "unknown"
derived_from:
- "raw/branch-notes/<branch-name>"
- "wiki/projects/<canonical-doc>"
related_projects:
- "ca-tmpl"
target_branch: ""
target_module: ""
audience: "self"
purpose: "branch-implementation-understanding"
last_reviewed: ""
status_label: "draft"
---
# {{title}}
> 이 문서는 이해를 위한 derived report입니다.
> SSOT는 `raw/branch-notes/`와 `wiki/projects/`의 canonical 문서입니다.
> 이 문서는 branch-note의 모든 내용을 보존하지 않고, 사람이 읽고 설명할 수 있도록 재구성합니다.
---
## 0. Executive Summary
### 한 문장 요약
> 이 기능은 `<무엇>`이 `<어떤 문제>`를 일으키지 않도록, `<어느 계층>`에서 `<어떤 계약>`으로 통제하는 기능이다.
### 이 보고서를 읽고 답할 수 있어야 하는 질문
- 이 기능은 왜 필요한가?
- 이 기능이 없으면 어떤 실패가 발생하는가?
- Clean Architecture 구조에서 어디에 위치하는가?
- 어떤 모듈이 무엇을 책임지고 무엇을 몰라야 하는가?
- 실제 구현은 어떤 원리로 동작하는가?
- 무엇을 테스트로 증명해야 하는가?
### 관련 문서
- Branch note:
- `raw/branch-notes/<branch-name>`
- Canonical project:
- `wiki/projects/<canonical-doc>`
- 관련 코드:
- `<module>/<path>`
- 관련 테스트:
- `<module>/<test-path>`
---
## 1. 이 기능은 어떤 문제를 해결하는가?
### 문제 정의
`<문제 설명>`
### 이 문제가 중요한 이유
- `<이유 1>`
- `<이유 2>`
- `<이유 3>`
### 이 기능이 없을 때 생기는 구조적 문제
- `<레이어 침투>`
- `<기술 누출>`
- `<실패 분류 불일치>`
- `<테스트로 감지 불가>`
---
## 2. 실제 실패 시나리오
### 시나리오 A. `<실패 이름>`
**상황**
`<현실적인 상황 설명>`
**실패 흐름**
```text
<입력/요청>
→ <잘못된 처리>
→ <장애/버그>
→ <운영 영향>
```
**이 기능이 막는 방식**
`<어떤 계약/테스트/모듈 경계가 이 실패를 막는지>`
---
### 시나리오 B. `<실패 이름>`
**상황**
`<현실적인 상황 설명>`
**실패 흐름**
```text
<입력/요청>
→ <잘못된 처리>
→ <장애/버그>
→ <운영 영향>
```
**이 기능이 막는 방식**
`<어떤 계약/테스트/모듈 경계가 이 실패를 막는지>`
---
## 3. Clean Architecture 안에서의 위치
### 관련 모듈
| 모듈 | 이 기능과의 관계 |
| ------------------- | ---------------- |
| domain-core | |
| application-core | |
| adapter-web | |
| adapter-persistence | |
| adapter-outbound | |
| shared-contract | |
| app-bootstrap | |
| sample-portfolio | |
### 의존 방향
```text
<허용되는 의존 방향>
```
### 이 기능의 소유 계층
- 주 소유 계층:
- 보조 계층:
- 소비 계층:
---
## 4. 각 모듈은 무엇을 책임지고 무엇을 몰라야 하는가?
| 모듈 | 책임 | 몰라야 하는 것 | 위반 예시 |
| ------------------- | ---- | -------------- | --------- |
| domain-core | | | |
| application-core | | | |
| adapter-web | | | |
| adapter-persistence | | | |
| adapter-outbound | | | |
| shared-contract | | | |
| app-bootstrap | | | |
| sample-portfolio | | | |
---
## 5. 핵심 설계 결정
| ID | 결정 | 이유 | 대안 | 선택하지 않은 이유 | 상태 |
| --- | ---- | ---- | ---- | ------------------ | ---- |
| D1 | | | | | |
| D2 | | | | | |
| D3 | | | | | |
### 가장 중요한 결정 1개
`<이 branch에서 가장 중요한 결정>`
### 이 결정이 중요한 이유
`<왜 이 결정이 전체 구조를 좌우하는지>`
---
## 6. 핵심 구현 원리
### 구현 원리 요약
`<핵심 구현 원리 설명>`
### 처리 흐름
```text
<입력>
→ <경계>
→ <변환>
→ <핵심 처리>
→ <외부 어댑터>
→ <응답/로그/테스트>
```
### 구현 위치
| 코드 위치 | 역할 | 관련 결정 |
| --------- | ---- | --------- |
| `<path>` | | D1 |
| `<path>` | | D2 |
| `<path>` | | D3 |
---
## 7. 상태나 데이터 모델은 어떻게 생기는가?
### 주요 타입
| 타입 | 위치 | 역할 | 노출 가능 여부 |
| ------------------- | ---- | ---- | -------------- |
| Request DTO | | | |
| Command/Query | | | |
| Domain Model | | | |
| Persistence Entity | | | |
| Response DTO | | | |
| Error/Envelope Type | | | |
### 변환 흐름
```text
HTTP JSON
→ Request DTO
→ Command / Query
→ Domain Model
→ Persistence Entity
→ Response DTO
→ Envelope
```
### 주의할 점
- DTO와 Domain을 섞지 않는다.
- Domain과 Persistence Entity를 동일시하지 않는다.
- 내부 진단 정보와 외부 응답 payload를 섞지 않는다.
---
## 8. 동시성/장애 상황에서 어떻게 동작하는가?
### 장애 분류
| 장애 상황 | 감지 위치 | 변환 결과 | client 노출 | log/trace |
| --------------------- | --------- | --------- | ----------- | --------- |
| validation failure | | | | |
| persistence failure | | | | |
| dependency timeout | | | | |
| authorization failure | | | | |
| concurrency conflict | | | | |
### 동시성 관련 동작
- transaction boundary:
- lock/retry/idempotency 관련 여부:
- 중복 실행 시 기대 동작:
- multi-instance 관련 제약:
---
## 9. 이 구현이 보장하는 것과 보장하지 못하는 것
### 보장하는 것
- `<자동 테스트나 컴파일 규칙으로 검증 가능한 것>`
- `<계약상 반드시 유지되는 것>`
### 보장하지 못하는 것
- `<정적 분석으로 잡기 어려운 것>`
- `<운영 환경에서 추가 검증이 필요한 것>`
- `<비즈니스 요구사항 자체의 정합성>`
### 표현 주의
아래 표현은 사용하지 않는다.
- 완벽히 보장한다
- 100% 방지한다
- 완전무결하다
- 모든 상황에서 안전하다
대신 아래처럼 쓴다.
- 빌드 시점에 감지한다
- 정적 import 위반을 차단한다
- 계약 위반을 테스트로 드러낸다
- 런타임 동적 우회는 코드 리뷰와 추가 테스트가 필요하다
---
## 10. 테스트는 무엇으로 증명해야 하는가?
| 테스트 종류 | 증명하는 것 | 실패해야 하는 조건 | 실행 명령 |
| ----------------- | ----------- | ------------------ | --------- |
| unit test | | | |
| contract test | | | |
| architecture test | | | |
| integration test | | | |
| smoke test | | | |
### 핵심 테스트
```bash
<명령어>
```
### 이 테스트가 깨졌을 때 의미
`<어떤 계약이 깨졌다는 뜻인지>`
---
## 11. Implementation Status
| 항목 | 상태 | 근거 | 비고 |
| -------- | ------------------------------------------------------------------------ | -------------------- | ---- |
| `<항목>` | `<decision-only / documented-only / local-verified / pending / unknown>` | `<문서/코드/테스트>` | |
### 상태 값 정의
| 상태 | 의미 |
| --------------- | ----------------------------------- |
| decision-only | 결정은 있으나 구현/검증은 아직 없음 |
| documented-only | 문서상 계약만 있음 |
| local-verified | 로컬 코드/테스트로 검증됨 |
| pending | 아직 착수 전 또는 잔여 작업 존재 |
| unknown | 근거 부족으로 판단 불가 |
---
## 12. Fact / Interpretation / Unknown
### 검증된 사실
- `<검증된 사실>` — 근거: `[[...]]`
### 내 해석
- `<내 해석>` — 이유: `<왜 그렇게 해석했는지>`
### 아직 모르는 것
- `<확인 필요 항목>`
---
## 13. 설명용 문장
### 30초 설명
`<짧은 설명>`
### 2분 설명
`<면접/리뷰에서 말할 수 있는 설명>`
### 깊게 질문받았을 때 답변
**Q. 왜 이렇게 나누었나?**
A. `<답변>`
**Q. 이 구조의 한계는 무엇인가?**
A. `<답변>`
**Q. 이게 실제 장애를 어떻게 막나?**
A. `<답변>`
---
## 14. 남은 리스크와 후속 작업
| 리스크 | 영향 | 확인 방법 | 후속 문서/branch |
| ------ | ---- | --------- | ---------------- |
| | | | |
---
## 15. Closure
- 이 보고서를 작성한 기준일:
- 반영한 branch-note:
- 반영한 코드 버전/커밋:
- 아직 반영하지 않은 자료:
- 다음에 읽을 문서:
@@ -0,0 +1,66 @@
---
title:
source_type: llm-generated
status: draft
confidence: unknown
tags: []
related_projects: []
last_reviewed:
---
# {{title}}
> Layer: `wiki/concepts/` — 일반 개념. 내 프로젝트 사실(`wiki/projects/`)은 `wiki-project-template` 사용 (raw 프로젝트 hub는 `project-template`).
## Summary
한두 문장으로 핵심 정의.
## Standard (공식 정의)
공식 문서 기준의 정의. 출처는 본문 끝 Sources 섹션에 명시.
## 한계 / 주의점
이 개념의 적용 한계, 흔한 오해, 트레이드오프. 공식 문서가 명시한 부분만 사실로, 그 외는 `needs-confirmation`으로 표기.
## Project Application
내 프로젝트에서 이 개념과 관련된 문서로 **링크**. 실제 구현 여부·검증 등급은 해당 project 문서에서 판정 (concept 문서는 등급을 직접 매기지 않음).
- `[[{{관련-project-문서}}]]`
## Claim-backed Knowledge
> 이 개념 문서의 핵심 설명은 raw source claim 으로 뒷받침되어야 한다.
> 공식 문서 claim, 회사 사례 claim, 내 프로젝트 decision 을 분리한다.
| Knowledge Point | Supporting Claims | Confidence | Notes |
|---|---|---|---|
| <개념 설명> | `raw/official-docs/<slug>.md#C1` | `high` | <공식 문서 기준> |
| <실무 적용 사례> | `raw/company-tech-blogs/<slug>.md#C2` | `medium` | <특정 회사 사례이므로 일반화 주의> |
## 내가 설명할 수 있어야 하는 것
- 이 개념의 공식 정의는 무엇인가?
- 어떤 문제를 해결하는가?
- 어떤 상황에서는 쓰면 안 되는가?
- 공식 문서가 말하지 않는 부분은 무엇인가?
- 회사 기술 블로그 사례를 일반 법칙처럼 말하면 안 되는 지점은 무엇인가?
- 내 프로젝트에서는 어떤 branch decision 으로 연결됐는가?
- 이 개념을 코드나 운영 환경에서 검증하려면 무엇을 확인해야 하는가?
## Interview Questions
- 면접에서 나올 법한 질문 1
- 면접에서 나올 법한 질문 2
## Do Not Overclaim
이 개념을 면접/이력서에서 말할 때 **과장하면 안 되는 지점**.
## 근거 자료
- [공식 문서 제목](https://example.com/...) — 핵심 출처
- `[[raw/{{원본-경로}}]]` — raw에 보존한 원본
@@ -0,0 +1,62 @@
---
title: YYYY-MM-DD 일일 노트
source_type: daily-note
status: raw
tags: [daily]
date: YYYY-MM-DD
branches: []
---
# YYYY-MM-DD
> Layer: `raw/daily-notes/` — 그날의 **혼합 일일 기록**. 그 자체는 wiki로 옮기지 않으며, `/ingest`가 promotable 항목만 추출해 다른 wiki 영역으로 보냅니다. 원본은 raw에 영구 보관.
## 활성 브랜치
오늘 작업한 브랜치 목록과 진행 상태. 브랜치 노트로 양방향 링크.
- `[branch-name]` (in-progress | review | merged) — `[[raw/branch-notes/{{branch-name}}]]`
## 오늘의 계획
브랜치별 항목은 `[branch-name]` 프리픽스. 브랜치 무관 항목은 프리픽스 없음.
- [ ] [branch-name] 항목 1
- [ ] [branch-name] 항목 2
- [ ] (no branch) 일반 항목
## 한 일
- [branch-name] 작업 1
- [branch-name] 작업 2
- (no branch) 일반 작업
## 배운 점
> wiki/concepts/로 promotable 후보
- 개념/사실 1
- 개념/사실 2
## 트러블슈팅
> raw/errors/ 또는 wiki/projects/ 또는 관련 branch-note의 "마주친 문제" 섹션으로 promotable 후보
- [branch-name] 이슈 1: 원인 / 해결
- 이슈 2
## 면접·포트폴리오로 옮길 만한 것
> **후보 표기만.** daily-note에서 `wiki/interview/` 또는 `wiki/portfolio/`를 직접 만들지 않습니다. 먼저 `/ingest`로 `wiki/projects/` 또는 `wiki/concepts/`에 canonical 추출 → 그 문서가 `reviewed | verified | published-ready`로 승급 → 그 후 `/interviewize` 또는 수동 작성.
- 항목 1 (→ 어떤 canonical 문서로 추출되어야 하는지)
- 항목 2
## 내일로 넘긴 것
- [branch-name] 항목 1
- 항목 2
## 잡담 / 회의 / 기타
> wiki로 promote할 가치가 낮은 일상 기록. 검색 archive로만 사용.
@@ -0,0 +1,191 @@
---
title: daily-task / develop / {{slug}}
source_type: daily-task
track: develop
status: raw
status_label: not-started
difficulty: intermediate
duration_estimate: 120
prerequisites: []
parent_project: ca-skeleton-operational-contract
parent_branch:
target_date: YYYY-MM-DD
created: YYYY-MM-DD
tags: [daily-task]
# 트랙 구분은 폴더 경로 + frontmatter `track:` 가 SSOT. tag 에 develop/infra 중복 금지.
# 추가 tag 는 도메인별 (예: `validation`, `testing`, `archunit`) 1~2개 권장.
---
# daily-task / develop / {{slug}}
> Layer: `raw/daily-tasks/develop/` — **개발 트랙 일일 실습 과제**. 사수가 신입에게 주는 형식의 자율 학습 과제. 매일 아침 1개 수행.
> `status_label`: `not-started` | `in-progress` | `done` | `abandoned`
> `difficulty`: `starter` (오늘이 처음) | `intermediate` (기본 흐름 익숙) | `advanced` (실패 모드 / 트레이드오프 탐구)
> `duration_estimate`: 분 단위. 기본 120분 (Pomodoro 4-5개). 단순 일정이 아니라 *완료 신호가 뜰 때까지* 의 자기 추정치.
>
> **체계 근거**: 본 template 구조는 두 raw 자료로 정당화된다 — 9-section anchor 는 vendor-normative 가이드 (`[[raw/company-tech-blogs/skillable-hands-on-lab-structure]]`), 단계 분할·자기평가·회고 원리는 deliberate-practice 개인 블로그 (`[[raw/company-tech-blogs/deliberate-practice-software-developers-redgreencode]]`) 기반. 두 자료 모두 *공식 best practice 가 아니다* — 본 template 도 best practice 가 아닌 **운영 가능한 학습 구조**로만 인용할 것.
## 부모 (필수)
- **Parent project**: `[[raw/project-notes/ca-skeleton-operational-contract]]` (또는 해당하는 다른 project-note)
- **연관 branch** (선택, 있을 때만): `[[raw/branch-notes/{{branch-slug}}]]`
> 본 과제가 어느 작업 묶음에 속하는지 명시. parent 없는 과제는 금지 (raw 영구 보관 정책 + ingest 시 추적 불가).
## 1. 학습 목표
> 3-5개 측정 가능 목표. "이 과제 끝났을 때 다음을 *할 수 있어야* 한다" 형식.
> 근거: `[[raw/company-tech-blogs/skillable-hands-on-lab-structure]]#SKILL-LAB-C1` — Learning Objectives 는 hands-on lab 의 7 functional spec 중 첫 anchor.
- [ ] L1: <할 수 있어야 하는 것 — 동사로 시작 (예: "ArchUnit rule 로 controller→domain 직접 의존을 빌드 실패로 검출할 수 있다")>
- [ ] L2: <...>
- [ ] L3: <...>
## 2. 스토리라인
> *왜* 이 과제가 필요한가. 실무 시나리오 1-2 문단. 단순한 코드 따라치기를 막는 anchor.
> 근거: `[[raw/company-tech-blogs/skillable-hands-on-lab-structure]]#SKILL-LAB-C2` — storyline 이 없으면 lab 은 "clicking things" 가 되고 학습자는 skill 향상 없이 끝난다.
(예시: "ca-tmpl 의 `feature-boundary-validation-mapping-contract` branch D7 결정 — controller 가 domain object 를 직접 반환하지 않는다 — 을 ArchUnit 으로 강제하려 한다. 다음 신입이 그 결정을 모르고 controller method 의 return type 에 domain entity 를 넣어도 build 가 통과되면 boundary contract 가 사실상 무력화된다. 오늘은 그 단 한 가지 시나리오만 막는 rule 을 작성하고 의도적인 위반으로 빌드를 깬다.")
## 3. 환경
> 사용 도구·버전·사전 셋업.
> 근거: `[[raw/company-tech-blogs/skillable-hands-on-lab-structure]]#SKILL-LAB-C1` — Prospective environment + Technologies used.
**개발 도구**:
- Java: <버전, e.g., 21 LTS>
- Build: <Gradle 8.x / Maven 3.9>
- IDE 권장: <IntelliJ IDEA 2025.x>
- 추가 라이브러리: <ArchUnit / MapStruct / RestAssured 등 — 버전 명시>
**사전 셋업**:
```bash
# repo clone / branch 전환
cd ~/workspace/ca-tmpl
git checkout -b daily-task/develop/{{slug}}
# 빌드 확인
./gradlew clean build
```
**예상 디렉토리 변경**:
- 추가/수정될 파일 경로 미리 명시 (예: `adapter-web/src/test/java/.../CleanArchitectureTest.java`)
## 4. 사전 지식
> 알아야 할 개념·결정. 모르면 wikilink 먼저 정독한 뒤 진행.
- `[[wiki/concepts/<concept-slug>]]` — <왜 필요한지 한 줄>
- `[[raw/branch-notes/<related-branch>]]` — <관련 결정>
- `[[raw/official-docs/<source-slug>]]` — <인용할 claim>
## 5. 단계별 과제
> Pomodoro (~25분) 단위로 분할. 각 단계는 *현재 능력보다 약간 높은* 도전이어야 한다 — 너무 쉬우면 학습 0, 너무 어려우면 좌절.
> 근거: `[[raw/company-tech-blogs/deliberate-practice-software-developers-redgreencode]]#DP-RGC-C2` (slightly higher than current ability — Ericsson 연구의 *개인 블로그 2차 인용*. 공식 best practice 표현 금지), `#DP-RGC-C5` (25-min Pomodoro 는 권고 시작점일 뿐 규범 아님).
### Step 1: <단계 제목> (~25min)
- **무엇을 (What)**: <구현해야 할 단위. 단일 commit 이 떠올라야 함>
- **어떻게 (How — hint, *spoiler 아님*)**: <어떤 클래스를 만져야 하는지 / 어떤 패턴을 찾아야 하는지. 코드 정답 X>
- **합격 신호 (Done when)**: <이 단계가 끝났음을 어떻게 알 수 있는가 — 명령어 / 로그 / 빨강↔초록 전환 / test name>
### Step 2: <단계 제목> (~25min)
- **What**:
- **How (hint)**:
- **Done when**:
### Step 3: <단계 제목> (~25min)
- **What**:
- **How (hint)**:
- **Done when**:
### 실패 모드 탐구> (~25min)
- **What**:
- **How (hint)**:
- **Done when**:
> *단계 갯수는 difficulty 에 따라*: starter=2, intermediate=3-4, advanced=4-5. 총 시간은 frontmatter `duration_estimate` 와 일치.
## 6. 검증
> 객관적 합격 기준. 단계 통과 = 측정 가능한 contract. *느낌* 으로 끝내지 않는다.
> 근거: `[[raw/company-tech-blogs/skillable-hands-on-lab-structure]]#SKILL-LAB-C4` (assessment = immediate feedback for success / additional help), `[[raw/company-tech-blogs/deliberate-practice-software-developers-redgreencode]]#DP-RGC-C3` (objective standard 로 평가 — 단 "objective standard" 의 구체 정의는 본 template 작성자가 합격 명령어로 조작적 정의해야 함).
**자동 검증**:
```bash
# 1) 빌드 + 단위 테스트
./gradlew clean build test
# 합격 기준: exit code 0
# 2) ArchUnit / contract test (해당 시)
./gradlew :adapter-web:test --tests '*CleanArchitectureTest'
# 합격 기준: PASS 로그
# 3) 의도적 위반 빌드 깨기 (해당 시 — rule 검증)
# 임시로 위반 코드 추가 → 빌드 → 실패 확인 → 위반 코드 제거
```
**수동 self-check**:
- [ ] 위 자동 명령 모두 exit 0
- [ ] 의도적 위반 시 *정확히* 의도된 rule 이름이 실패 메시지에 포함됨
- [ ] L1~L3 학습 목표가 실제로 *할 수 있다* 상태인지 (1줄로 설명 가능)
- [ ] commit 메시지가 "왜" 를 답함 ("Add X" 가 아니라 "Enforce X to prevent Y")
## 7. 결과물
> 과제가 끝났을 때 남는 산출물. 휘발성 학습이 아니라 *재사용 가능한 흔적* 을 남긴다.
> 근거: `[[raw/company-tech-blogs/skillable-hands-on-lab-structure]]#SKILL-LAB-C1` — Outcomes 는 7-component spec 의 마지막 anchor.
- **commit / PR**:
- 브랜치: `daily-task/develop/{{slug}}`
- commits: <해시 + 1줄 메시지>
- PR URL (있다면):
- **신규/변경 파일**:
- `<path/to/file>` — <역할 한 줄>
- **학습한 개념** (wiki/concepts 로 ingest 후보):
- <개념 1> — `/ingest` 시점에 `wiki/concepts/<slug>` 로 추출 가능 여부 메모
- **다음 과제 thread** (실수·궁금증·심화 주제):
- <오늘 막혔던 지점에서 자연스럽게 파생되는 과제 후보 — 내일 또는 다음 주 daily-task 시드>
## 8. 회고
> 과제 끝난 직후 5분 회고. 빈칸으로 두지 말 것. 빈 회고 = 학습 손실.
> 근거: `[[raw/company-tech-blogs/deliberate-practice-software-developers-redgreencode]]#DP-RGC-C4` — "After you finish each problem, ask yourself if you can improve any aspect of your problem-solving process based on your experience with that problem."
- **막혔던 곳** (몇 분 / 어디서):
- **예상과 다른 점** (가정이 깨진 부분):
- **다음 반복에서 개선할 점** (방법론 / 도구 / 정보 수집 순서):
- **부수 효과로 발견한 것** (의도 외 학습):
- **이 과제의 난이도가 적정했는가** (`너무 쉬움` / `적정` / `너무 어려움` — frontmatter `difficulty` 조정 신호):
## 9. 출처
> 본 과제의 구조 근거 + 도메인 근거.
| Source | 정당화 영역 |
|---|---|
| `[[raw/company-tech-blogs/skillable-hands-on-lab-structure]]` | template 9-section 구조 자체 (§1, §2, §3, §6, §7) |
| `[[raw/company-tech-blogs/deliberate-practice-software-developers-redgreencode]]` | §5 단계 분할 + §6 objective 평가 + §8 reflection 원리 |
| `[[raw/official-docs/<...>]]` | 도메인 결정 근거 (Spring Boot / Java spec / Jackson 등) |
| `[[raw/branch-notes/<...>]]` | 본 과제가 검증하려는 branch 결정 |
## 10. 완료 후 정리
> done 으로 바뀌는 순간 채움. `/ingest` 가 이 섹션을 기준으로 wiki 영역으로 promotable 항목 추출.
- **최종 status_label**: `done` | `abandoned`
- **소요 시간 실측**: <분> (vs frontmatter `duration_estimate` <분>) — 차이 분석은 §8 회고에
- **promotable 후보**:
- `actually-implemented` → 어느 branch-note 의 어느 결정과 연결되는지
- `locally-verified` → 어떤 명령으로 검증됐는지
- **추출하지 않을 항목** (단순 학습 / 폐기):
@@ -0,0 +1,238 @@
---
title: daily-task / infra / {{slug}}
source_type: daily-task
track: infra
status: raw
status_label: not-started
difficulty: intermediate
duration_estimate: 120
prerequisites: []
parent_project: ca-skeleton-operational-contract
parent_branch:
target_date: YYYY-MM-DD
created: YYYY-MM-DD
tags: [daily-task, infra]
# 트랙 구분은 폴더 경로 + frontmatter `track:` 가 SSOT.
# `infra` 는 L3 Domain 태그 (운영/인프라 영역 검색용). 추가 tag 는 도메인별 (예: `observability`, `kubernetes`) 0~2개.
---
# daily-task / infra / {{slug}}
> Layer: `raw/daily-tasks/infra/` — **인프라 / 운영 트랙 일일 실습 과제**. 사수가 신입에게 주는 형식의 자율 운영 과제. 매일 아침 1개 수행.
> `status_label`: `not-started` | `in-progress` | `done` | `abandoned`
> `difficulty`: `starter` (도구 처음) | `intermediate` (기본 흐름 익숙) | `advanced` (장애 / 트레이드오프 / SLO 탐구)
> `duration_estimate`: 분 단위. 기본 120분. develop 트랙과 달리 *대기 시간 (apply / probe / metric 수렴)* 이 포함됨에 유의.
>
> **체계 근거**: 본 template 구조는 두 raw 자료로 정당화된다 — 9-section anchor 는 vendor-normative 가이드 (`[[raw/company-tech-blogs/skillable-hands-on-lab-structure]]`), 단계 분할·자기평가·회고 원리는 deliberate-practice 개인 블로그 (`[[raw/company-tech-blogs/deliberate-practice-software-developers-redgreencode]]`) 기반. 두 자료 모두 *공식 best practice 가 아니다*.
>
> **develop 트랙과의 차이**: §3 환경은 *작업 host + target cluster + kubeconfig context*, §5 단계는 *manifest 작성 → apply → 관측 → 롤백 drill* 흐름, §6 검증은 *kubectl / promql / log query / smoke test*, §7 결과물은 *applied manifest + dashboard URL + alert rule + runbook stub*, §11 운영 회복력 anchor 추가.
## 부모 (필수)
- **Parent project**: `[[raw/project-notes/ca-skeleton-operational-contract]]` (또는 해당하는 다른 project-note — 예: 사용자 인프라 개요)
- **연관 branch** (선택, 있을 때만): `[[raw/branch-notes/{{branch-slug}}]]`
> 본 과제가 어느 작업 묶음에 속하는지 명시. parent 없는 과제는 금지.
## 1. 학습 목표
> 3-5개 측정 가능 목표. "이 과제 끝났을 때 다음을 *할 수 있어야* 한다" 형식. 인프라 트랙은 *관측 / 진단 / 롤백* 동사를 의식적으로 섞을 것.
> 근거: `[[raw/company-tech-blogs/skillable-hands-on-lab-structure]]#SKILL-LAB-C1`.
- [ ] L1: <동사로 시작 (예: "Spring Boot actuator `/actuator/health/readiness` 를 k8s readinessProbe 로 연결하고 의도적 DB 단절 시 not-ready 가 30초 안에 노출됨을 prometheus 로 확인할 수 있다")>
- [ ] L2: <...>
- [ ] L3: <...>
## 2. 스토리라인
> *왜* 이 인프라 작업이 필요한가. 실무 운영 시나리오 1-2 문단. SLO / 장애 / 비용 anchor 가 자연스럽다.
> 근거: `[[raw/company-tech-blogs/skillable-hands-on-lab-structure]]#SKILL-LAB-C2` (storyline 없으면 "clicking things").
(예시: "현재 ca-tmpl staging cluster 의 readiness probe 는 항상 200 을 반환하는 `/health` 를 본다. 즉 DB unavailable 이어도 pod 가 ready 로 표시돼 트래픽이 흘러 5xx 가 양산된다. 오늘은 readiness 를 `health/readiness` 로 분리하고 DB connection failure 시 *unhealthy* 가 30초 내에 표면화되는지, kube-state-metrics + prometheus 로 확인한다.")
## 3. 환경
> 작업 호스트 · 대상 시스템 · 도구 버전 · context.
> 근거: `[[raw/company-tech-blogs/skillable-hands-on-lab-structure]]#SKILL-LAB-C1` (Prospective environment + Technologies used).
**작업 호스트**:
- 로컬 macOS / Linux / WSL2 — <명시>
**대상 환경**:
- Cluster: <local kind / k3s / minikube / staging cluster name>
- Namespace: <e.g., `ca-tmpl-staging`>
- Kubeconfig context: <명시>
**도구 버전**:
- `kubectl`: <e.g., 1.30>
- `helm`: <3.15>
- `docker` / `podman`: <24.x>
- (Optional) `terraform`, `kustomize`, `k9s`, `stern`, `kubectx`: <버전>
- 관측: Prometheus <v2.50>, Grafana <11.x>, Loki / OpenTelemetry collector <버전>
**사전 셋업**:
```bash
# context 전환 확인
kubectl config current-context
kubectl get ns <namespace>
# 작업 디렉토리
cd ~/workspace/ca-tmpl-infra
git checkout -b daily-task/infra/{{slug}}
# 현재 상태 스냅샷 (롤백 reference)
kubectl get all -n <namespace> -o yaml > /tmp/snapshot-pre-{{slug}}.yaml
```
**변경 예정 리소스**:
- `<manifest path or k8s resource>` — <어떤 변경>
## 4. 사전 지식
> 알아야 할 개념·결정·운영 규약.
- `[[wiki/concepts/<concept-slug>]]` — <왜 필요한지>
- `[[raw/project-notes/ca-skeleton-operational-contract]]` — <§N (e.g., §15 runtime/lifecycle) 인용>
- `[[raw/official-docs/<source-slug>]]` — <인용할 claim>
## 5. 단계별 과제
> *Manifest 작성 → apply → 관측 → 롤백 drill* 의 자연스러운 흐름. 각 단계 25분 ± 대기시간. infra 는 *apply 후 metric 수렴* 같은 비-CPU 대기가 있으니 시간 추정에 포함.
> 근거: `[[raw/company-tech-blogs/deliberate-practice-software-developers-redgreencode]]#DP-RGC-C2` (slightly higher than current), `#DP-RGC-C5` (25-min Pomodoro 권고 시작점).
### 베이스라인 측정 (~20min)
- **What**: 변경 전 상태를 *수치* 로 기록. metric / log / probe 응답.
- **How (hint)**: `kubectl get` / `kubectl describe` / promql query / log grep
- **Done when**: 베이스라인 수치 3개 이상이 본 노트 §7 에 기록됨
### 설정 작성 (~30min)
- **What**: <변경할 manifest / Dockerfile / helm values / actuator config>
- **How (hint)**: 어떤 field 가 핵심인가, 어떤 default 를 override 해야 하는가
- **Done when**: 로컬 lint 통과 (`kubectl apply --dry-run=server -f ...`), diff 검토 완료
### Step 3: Apply + 관측 (~25min, 대기 포함)
- **What**: 실제 apply 후 *수렴 시간* 측정 + 의도된 동작 확인
- **How (hint)**: `kubectl rollout status`, prometheus `up{job=...}`, alert 발화 여부, `kubectl logs --previous`
- **Done when**: 의도된 metric / probe 변화가 promQL 로 확인 가능
### 롤백 drill (~25min)
- **What**: 본 변경의 *실패 모드* 를 의도적으로 발생 → 자동 복구 또는 수동 롤백 검증
- **How (hint)**: chaos (e.g., DB 단절, pod kill, network delay), 또는 rollback 명령 직접 실행
- **Done when**: 시스템이 알려진 상태로 복귀 + 사후 metric / log 정상
### 대시보드 작성 (~20min)
- **What**: 본 변경을 관측하는 alert rule + grafana panel
- **How (hint)**: PromQL recording rule, alert threshold, runbook link
- **Done when**: alert rule lint 통과, dashboard JSON commit
> *단계 갯수 권고*: starter=3, intermediate=4-5, advanced=5+chaos. 총 시간은 frontmatter `duration_estimate` 와 일치.
## 6. 검증
> 인프라 검증 = *명령 + metric + log + probe* 4가지 채널 중 ≥2개 교차 확인. 단일 채널만 의존 금지.
> 근거: `[[raw/company-tech-blogs/skillable-hands-on-lab-structure]]#SKILL-LAB-C4` (immediate feedback), `[[raw/company-tech-blogs/deliberate-practice-software-developers-redgreencode]]#DP-RGC-C3` (objective standard).
**자동 검증** (각 명령 + 합격 기준):
```bash
# 1) Probe / health
curl -fsS http://<host>:<port>/actuator/health/readiness
# 합격 기준: HTTP 200 + status: UP
# 2) k8s 리소스 상태
kubectl rollout status deployment/<name> -n <namespace> --timeout=60s
# 합격 기준: deployment 가 successfully rolled out
# 3) PromQL — 의도된 metric 수렴
# 예: 1분 평균 readiness probe success rate
# promql: avg_over_time(probe_success{job="kubernetes-pods"}[1m])
# 합격 기준: 변화 시점이 기대 시간 ± 10초 내
# 4) Log 검증
kubectl logs deployment/<name> -n <namespace> --tail=200 | grep -E '<expected log line>'
# 합격 기준: 의도된 log entry 발견 (또는 *없어야 할* line 부재)
# 5) Smoke test (해당 시)
./scripts/smoke-test.sh <env>
# 합격 기준: exit code 0
```
**수동 self-check**:
- [ ] 위 4-5개 명령 중 ≥2 채널이 교차 확인됨
- [ ] 의도적 실패 시 정확히 의도된 alert 가 발화 (Step 4 결과)
- [ ] 롤백 명령으로 *완전히* 베이스라인으로 복귀 가능 (Step 1 수치와 일치)
- [ ] L1~L3 학습 목표가 실제로 수행 가능한 상태
- [ ] manifest commit 메시지가 "왜" 를 답함
## 7. 결과물
> 인프라 트랙 산출물 = *applied manifest + 측정값 + dashboard / alert + runbook stub*.
> 근거: `[[raw/company-tech-blogs/skillable-hands-on-lab-structure]]#SKILL-LAB-C1`.
- **commit / PR**:
- 브랜치: `daily-task/infra/{{slug}}`
- commits: <해시 + 1줄>
- PR URL (있다면):
- **변경된 manifest / 설정**:
- `<path>` — <역할 한 줄>
- **측정값** (§5 Step 1 베이스라인 vs Step 3 적용 후):
- <metric / probe / log line>: before=<값> → after=<값>
- **Dashboard / Alert**:
- Grafana panel URL: <또는 JSON path>
- Alert rule: <name, threshold, runbook link>
- **Runbook stub** (이 변경으로 새 alert 가 생겼다면):
- 알람 발생 시 1차 확인: <명령 1-2줄>
- 즉시 fail-fast / degrade 가능 분류: <명시>
- **학습한 개념** (wiki/concepts 로 ingest 후보):
- **다음 과제 thread**:
## 8. 회고
> 빈 회고 = 학습 손실. 인프라 트랙은 *측정값 vs 예상* 의 괴리를 특히 기록.
> 근거: `[[raw/company-tech-blogs/deliberate-practice-software-developers-redgreencode]]#DP-RGC-C4`.
- **막혔던 곳** (몇 분 / 어디서 — apply 대기 / probe timing / metric label mismatch 등):
- **예상과 다른 점** (가정이 깨진 부분 — 수렴 시간 / probe 동작 / cluster 자동 동작):
- **다음 반복에서 개선할 점**:
- **부수 효과로 발견한 것** (의도 외 metric / log / 이벤트):
- **이 과제의 난이도가 적정했는가** (frontmatter `difficulty` 조정 신호):
## 9. 출처
| Source | 정당화 영역 |
|---|---|
| `[[raw/company-tech-blogs/skillable-hands-on-lab-structure]]` | template 9-section 구조 자체 |
| `[[raw/company-tech-blogs/deliberate-practice-software-developers-redgreencode]]` | §5 단계 분할 + §6 objective 평가 + §8 reflection |
| `[[raw/official-docs/<...>]]` | 도메인 근거 (Spring actuator / k8s probe / Prometheus / Grafana 등) |
| `[[raw/project-notes/ca-skeleton-operational-contract]]` | 본 과제가 검증하려는 운영 계약 §N |
## 10. 완료 후 정리
- **최종 status_label**: `done` | `abandoned`
- **소요 시간 실측**: <분> (vs frontmatter `duration_estimate`) — 차이는 §8 회고에
- **promotable 후보**:
- `actually-implemented` → 어느 운영 계약 §N 과 연결되는지
- `locally-verified` → 어떤 명령으로 검증됐는지
- `prod-verified` → (해당 시) 운영 환경 검증 시점 + 로그/측정값 reference
- **추출하지 않을 항목** (단순 학습 / 실험 / 폐기):
## 11. 운영 회복력
> develop 트랙에 *없는* infra 트랙 전용 anchor. 본 과제가 시스템 회복력에 어떤 영향을 주는지 명시.
- **본 변경이 도입하는 새 실패 모드**:
- **새 실패 모드의 fail-fast vs degrade 분류**:
- **모니터링 누락 위험** (이 변경 후 *못 보게 되는* metric/log):
- **롤백 트리거 조건** (어떤 측정값이 어떤 임계치 초과 시 롤백):
- **연관 alert / runbook** (`[[raw/project-notes/ca-skeleton-operational-contract]]#28` Operational Runbook 와의 정합):
@@ -0,0 +1,98 @@
---
title: error / {{short-error-slug}}
source_type: error-note
status: raw
related_branches: []
related_projects: []
tags: [error]
created: YYYY-MM-DD
status_label: open
---
# error: {{short-error-slug}}
> Layer: `raw/errors/` — 작업 중 마주친 **단일 실패·트러블슈팅 기록**. 해결되면 wiki/concepts(공통 패턴) 또는 wiki/projects(프로젝트 특화)로 `/ingest` 시 일부 추출 가능. 원본은 raw에 영구 보관.
> `status_label`: `open` | `investigating` | `resolved` | `workaround` | `wontfix` | `needs-confirmation`
> **Citation / honesty discipline (필수)**:
>
> - `## 증상` 의 에러 메시지는 **원문 그대로** (paraphrase 금지). stack trace 핵심 부분만 발췌해도 verbatim 유지.
> - `## 재현 절차` 는 _타인이 그대로 재현할 수 있는지_ 기준으로 명령·파일 변경·기대값/실제값을 적는다. 빈 상태로 두지 말 것.
> - `## 조사 단계` 는 시간순으로 시도와 결과를 모두 기록한다 (막다른 길 포함). 사후에 "원인은 X였다" 만 적으면 재발 시 패턴 인식 불가능.
> - `## 근본 원인` 의 "직접 원인 / 근본 원인 / 트리거 조건" 셋을 분리. "직접 원인" 만 적으면 다음 비슷한 상황을 인지 못 함.
> - `## 회고` 의 "빨리 감지하는 신호" 는 _다음에 같은 에러를 더 빨리 잡기 위한_ 키워드 (예: "메시지에 `Read-only file system` 이 나오면 sandbox 권한 의심"). 추상적인 교훈만 적지 않는다.
## 부모
> 이 에러가 어느 작업 묶음에 속하는지 명시. **최소 1개 필수.** 작업 외 발생 시(예: 환경 셋업 중) `[[raw/project-notes/<project>]]` 로 연결.
- `[[raw/branch-notes/{{branch-name}}]]`
- (또는) `[[raw/project-notes/{{project-name}}]]`
## 증상
> 무슨 일이 일어났는가. 에러 메시지 원문, stack trace 핵심 부분, 발생 화면/명령 등.
- 에러 메시지 (원문 그대로):
```text
<verbatim message>
```
- 발생 컨텍스트: <어떤 명령·요청·UI 동작에서 발생>
- 발생 시점: YYYY-MM-DD HH:MM
- 발생 환경: <local / dev / staging / prod / CI>
- 재현 가능 여부: `always` | `sometimes` | `once`
## 재현 절차
> "타인이 이걸 보고 재현할 수 있는가" 기준. 명령 한 줄 또는 step-by-step.
1. <단계 1>
2. <단계 2>
3. <기대 결과> vs <실제 결과>
## 조사 단계
> 시도한 것 + 결과를 시간 순으로. 막다른 길도 기록 (다음에 같은 길로 안 가기 위함).
- YYYY-MM-DD HH:MM — <시도한 것> → <결과·관측>
- YYYY-MM-DD HH:MM — <시도한 것> → <결과·관측>
## 근본 원인
> 사실에 입각해 결론. 추측이라면 `needs-confirmation` 으로 표시.
- 직접 원인:
- 근본 원인:
- 트리거 조건:
## 근거 (해결 근거가 된 자료, 최소 1개+ 권장)
> 공식 문서·기술 블로그·이슈 트래커 링크. raw에 보관한 원문 발췌가 있다면 `[[raw/official-docs/...]]` 또는 `[[raw/company-tech-blogs/...]]` 로 연결.
- `[[raw/official-docs/<...>]]` — <어떤 부분이 근거인지 한 줄>
- `[[raw/company-tech-blogs/<...>]]` — <어떤 부분이 근거인지 한 줄>
- 외부 URL (raw에 안 넣은 즉석 참조): <url> — <한 줄 메모>
## 해결
> 어떻게 막았는가. 코드/설정/명령 변경 사항을 구체적으로.
- 적용한 조치:
- 검증 방법: <테스트·로그·재현 명령으로 확인>
- 잔여 위험 / 후속 작업: <있다면>
## 회고
> 다음번에 같은 에러를 더 빨리 잡으려면 무엇을 기억할지.
- 빨리 감지하는 신호:
- 예방 체크리스트 항목 후보:
- wiki로 끌어올릴 가치가 있는 일반화된 교훈: <있다면 wiki/concepts 추출 후보로 메모>
## 관련
> 같은 작업 묶음 내 다른 raw 문서.
- 트리거된 daily note: `[[raw/daily-notes/YYYY-MM-DD]]`
- 관련 에러 (선행/후속/유사): `[[raw/errors/<...>]]`
- 관련 wiki 개념: `[[wiki/concepts/<...>]]` (이미 검증된 요약 있을 시)
@@ -0,0 +1,129 @@
---
title: (강사 설명) {{무엇을, 한 줄로}}
source_type: explainer
status: draft
confidence: medium
tags: []
related_projects: []
last_reviewed:
---
# (강사 설명) {{제목 — 정의가 아니라 "무엇을 할 수 있게 되는가" 로}}
> Layer: `wiki/explainer/` — **derived(파생) 교육 문서.** "나의 진짜 이해" 를 위한 1타강사 칠판이다.
> 정확한 사실·근거·검증 등급은 여기서 만들지 않는다. 전부 canonical 에서 가져온다:
> - 개념·대안·근거: `[[wiki/concepts/{{concept-slug}}]]`
> - 내 프로젝트 실제 구현·검증 범위: `[[wiki/projects/{{project}}/{{slug}}]]` (있을 때만)
>
> 이 문서의 **비유는 의도적으로 부정확**하다 (이해를 위한 단순화). 비유를 사실로 인용하지 마라. 면접에서 말할 땐 canonical 의 표현을 써라.
<!--
작성 원칙 (HARD RULE — 지우지 말고 작성 후 검토):
1. derived 다. 새 claim 을 만들지 않는다. 전부 canonical 의 재구성이다. (코드 인용은 ground-truth repo 에서, file:line 캡션과 함께.)
2. **학습 계약 먼저(§0).** "무엇을 알고 와서(선행지식), 끝나면 무엇을 어디까지 설명할 수 있나(수료역량)"를 표로 못박는다. 이게 이 템플릿의 1급 시민이다 — 학습자가 진입↔도달을 스스로 측정하게 한다.
3. 정의로 시작하지 않는다. §1 은 고통/문제 장면.
4. **하나의 관통 줄기(through-line).** 처음부터 끝까지 한 예시("요청 1건의 생애" 등)를 따라간다. 큰 그림(§3)에서 정상 경로를 깔고, §4 에서 그 1건이 각 안전장치를 *통과 순서대로* 만나게 한다.
5. **난이도 레인.** 각 본문 모듈 제목 끝에 `[신입 필수]` / `[심화]` / `[참조]` 라벨. §0 에 "신입 최소 완주 경로"를 명시(어디까지 읽으면 수료역량 달성).
6. **just-in-time 용어.** 용어는 *처음 쓰는 모듈 시작*에 "새 용어" 미니 박스로 정의한다. 전체 용어집(§참조)은 *복습 치트시트*이지 처음 배우는 곳이 아니다.
7. **모듈마다 형성 평가.** 각 본문 모듈 끝에 `<details>` 자가 점검 1~3문항(정답은 본문 위치/메서드명을 가리킴). 끝에 몰지 말 것.
8. 톤: 존댓말 아님. 크리스프 평서문 + 직접 호명. 단정 과장 금지(canonical 의 과장 금지 준수). 비유가 사실을 왜곡할 지점은 "강사의 한마디"로 명시 보정.
9. **## 백बोन 헤딩(§0~§3 · 정의 · 자가 점검 · Sources)은 글자 그대로 유지**한다. structure-lint(`wiki_structure_lint.py`)가 헤딩을 거의-정확매칭하므로, 백본 헤딩을 바꾸거나 인스턴스값(프로젝트명/주제)을 백본 헤딩에 끼우면 MISSING_SECTION 오탐이 난다. **인스턴스값·난이도 라벨은 백본 헤딩이 아니라 그 아래 첫 줄(부제, bold)에 쓴다.** 본문 모듈은 `###` 으로 자유롭게(린트는 `##` 만 검사).
-->
---
## §0. 학습 계약 — 시작 전에 꼭 읽기
> 이 수업이 가르치는 것을 한 문장으로. 그 다음 네 블록을 *표로* 채운다.
**이 수업을 마치면 — 수료 역량** (이 질문들에 *이 깊이로* 답하게 된다):
| # | 질문 | 답에 반드시 들어가야 할 키워드 |
|---|---|---|
| E1 | {{핵심 질문 1}} | {{기대 답변 깊이}} |
| E2 | {{...}} | {{...}} |
**시작 전 알아야 할 것 — 선행 지식** (self-check 통과하면 OK):
| 알아야 할 것 | self-check (한 줄로 답되면 통과) | 모르면 |
|---|---|---|
| {{선행 1}} | "{{스스로 던질 질문}}" | {{보충 링크/섹션}} |
**난이도 레인 & 최소 완주 경로:** 본문 제목의 `[신입 필수]` / `[심화]` / `[참조]` 를 읽는 법. "신입은 {{§N}} 까지만 읽어도 E1~E{{k}} 달성. [심화]는 1회독 후."
**관통 줄기 🧵:** 이 수업은 처음부터 끝까지 **"{{예시 1건}}의 생애"** 를 따라간다. ({{가상/실제}} 여부 명시.)
---
## §1. 한 장면 — 5초 만에 고통 느끼기
> 정의 금지. 이 주제가 없으면 무엇이 *터지는지* 구체적 장면. 코드/숫자/실패가 보이게.
> 마지막은 "그래서 진짜 고민은 이 한 줄" 로 §2 에 넘긴다.
---
## §2. 단 하나의 축
> **부제(첫 줄, bold)에 인스턴스 축 이름**: 예) "정합성 ↔ 가용성". (백본 헤딩엔 넣지 말 것 — 원칙 9.)
> 모든 선택이 답하려는 *공통 질문* 을 한 축(axis)으로 압축. 양 끝 신념을 ASCII 한 줄로 대비.
> 메시지: "누가 맞고 틀린 게 아니라, 무엇을 더 두려워하는지가 다르다."
```text
{{왼쪽 끝 신념}} ◄───────────────────────────────► {{오른쪽 끝 신념}}
{{선택지 위치들}}
```
---
## §3. 큰 그림
> **부제(첫 줄, bold)에 인스턴스 제목**: 예) "{{요청 1건}}의 정상 항해".
> 관통 줄기의 *정상 경로* 1회를 깐다. 레이어 경계(누가 누구를 부르나) + 입·출력(구체 값/JSON) 을 보인다.
> 아직 안 본 영역은 🌫️(미지의 영역)로 표시하되, 경계를 *넘는 값* 은 보여준다. 마스터 시퀀스 다이어그램 1장은 여기.
<!--
─────────────────────────────────────────────────────────────────────
본문 (코드로 따라가기) — 백본 아니라 ### 모듈로 자유롭게. 주제별 가변.
관통 줄기의 1건이 *통과하는 순서대로* 안전장치/메커니즘을 한 모듈씩.
각 모듈은 아래 패턴을 반복한다 (### 이므로 structure-lint 가 강제하지 않음):
### {{모듈 제목}} [신입 필수|심화|참조]
> **새 용어:** {{이 모듈에서 처음 쓰는 용어 2~3개 just-in-time 정의}}
{{실제 코드 블록 + 📄 file:line 캡션 + 한 줄씩 풀이}}
{{필요시 mermaid: sequence/state/class diagram}}
<details><summary>✅ 이해 점검</summary>
1. {{질문}} (정답: {{본문 위치/메서드명}})
</details>
─────────────────────────────────────────────────────────────────────
-->
---
## 그래서 어떤 문제로 "정의" 했나
> **부제(첫 줄, bold)에 인스턴스**: "{{프로젝트}} 가 {{이 조합}}을 고른 이유". (백본 헤딩엔 넣지 말 것.)
> 메시지: "그게 우월해서" 가 아니라 "내가 문제를 그렇게 정의했기 때문". 내가 세운 규칙/제약이 답을 결정했음을 보인다.
> 그 다음 *검증된 사실만* (project 문서에서) 간략히. 검증 범위(로컬/dev/prod) 와 "말하면 안 되는 범위" 를 분명히.
- 내가 세운 규칙 / 문제 정의: {{...}} → 이 규칙이 답을 어떻게 좁혔는가
- 실제로 한 것 (`actually-implemented` / `locally-verified` 등급만): {{...}} — 자세히는 `[[wiki/projects/{{project}}/{{slug}}]]`
- 검증은 어디까지 / 무엇을 말하면 안 되는가: {{...}}
---
## 자가 점검 — 다시 처음 장면으로
> §1 장면으로 복귀. 답을 *외운 게 아니라 재구성할 수 있는지* 확인하는 질문 5~6개.
> 최소 1개는 "문제 정의를 바꾸면 답이 어떻게 바뀌는가", 1개는 "흔한 과장을 반박하라", 1개는 "한 단계 더 깊은 메커니즘".
> (모듈별 형성 평가와 별개로, 전체를 관통 줄기로 다시 엮는 종합 점검.)
1. {{문제 정의를 바꾸면?}}
2. {{흔한 단정/과장을 반박하라}}
3. {{한 단계 더 깊은 메커니즘/비용}}
---
## 근거 자료 (이 설명의 출처 — 모두 canonical)
- `[[wiki/concepts/{{concept-slug}}]]` — 개념 정의 / Claim-backed 근거 / 과장 금지 (사실의 금고)
- `[[wiki/projects/{{project}}/{{slug}}]]` — 내 프로젝트 실제 구현 · 검증 범위 (있을 때만)
@@ -0,0 +1,93 @@
---
title: interview-prep / {{short-question-slug}}
source_type: interview-prep
status: raw
related_branches: []
related_projects: []
tags: [interview-prep]
created: YYYY-MM-DD
status_label: collecting
---
# interview-prep: {{short-question-slug}}
> Layer: `raw/interviews/` — 면접 질문 **원본 수집·연구 노트**. 다듬어진 답변은 `/interviewize` 후 `wiki/interview/`에 별도 작성. 원본은 raw에 영구 보관.
> `status_label`: `collecting` | `drafting` | `ready-for-derive` | `derived` | `needs-confirmation`
> **Citation discipline (필수)**:
>
> - `## 답변 재료` 의 각 "사실" 항목은 다음 셋 중 하나로 근거를 같이 적는다:
> 1. branch-note 의 **Decision ID** (예: "근거: `feature-X.md` D3, D9").
> 2. 외부 source 의 **claim ID** (예: `AT-TX-C5`, `SPRING-TX-MGR-C6`) — anchor 인용 가능하면 `<path>.md#<claim-id>`.
> 3. branch-note 의 **section** 인용 (예: `feature-X.md §결정 사항`).
> - "경험" 은 _내가 직접 한_ 것만. 추론은 "의견 / 해석" 으로 분리.
> - "트레이드오프" 는 majority vs minority position 을 명시 (다수파 / 소수파 / 표준 / 비표준). 한쪽만 적으면 답변이 단편적이 된다.
> - `## 답변 경계 / Answer boundary` 의 "절대 과장하지 말 것" 은 반드시 채운다 — local-verified 를 prod-verified 처럼 말하지 않기 위한 self-check.
> - `## 미해결 / Unknown` 의 "확인 방법" 도 비워두지 말 것 — "공식 문서 다시 보기" / "실 실험" / "후속 branch" 등 구체 방법 명시.
## 부모
> 이 질문이 어느 작업·프로젝트에서 나올 수 있는지 명시. **최소 1개 필수.** 특정 작업과 무관한 일반 CS 질문이면 `[[raw/project-notes/<project>]]` (전체 프로젝트 차원) 또는 미연결도 허용 (단, frontmatter `related_projects` 는 채울 것).
- `[[raw/branch-notes/{{branch-name}}]]` — <왜 이 branch에서 이 질문이 나올 수 있는지 한 줄>
- (또는) `[[raw/project-notes/{{project-name}}]]`
## 질문
> 면접에서 받을 수 있는 질문 원형. 받았다면 받은 형태 그대로.
- 질문 원문:
- 출처: <실제 받은 질문 / 예상 질문 / 책·블로그에서 발견 / JD에서 유추>
- 받은 날짜·맥락 (실제 받은 경우):
## 질문 의도 추론
> 면접관이 이 질문으로 무엇을 평가하려 하는지.
- 핵심 평가 대상: <개념 이해 / 운영 경험 / 트레이드오프 인식 / 의사결정 경험 / 한계 인식>
- 함정 / 흔히 빠지는 답변 패턴:
- 따라올 만한 후속 질문:
## 답변 재료
> 이 단계는 raw. 정리된 답변이 아님. 떠오르는 사실·일화·트레이드오프를 자유롭게 모음.
- 사실 1 (근거: `[[raw/branch-notes/...]]` 또는 `[[raw/official-docs/...]]`):
- 사실 2:
- 내가 직접 한 경험 (있다면): `[[raw/branch-notes/...]]`
- 트레이드오프:
- 한계 / "이건 안 해봤다":
## 근거 (답변의 사실 근거)
> 면접에서 자신 있게 말하려면 사실 근거가 있어야 함. raw 또는 wiki canonical 링크.
- `[[raw/official-docs/<...>]]` — <인용할 만한 핵심 사실>
- `[[raw/company-tech-blogs/<...>]]` — <인용할 만한 사례>
- `[[wiki/concepts/<...>]]` — (검증된 요약이 있다면)
- `[[wiki/projects/<...>]]` — (내 프로젝트 사실, 있다면)
## 미해결
> 이 질문에 답하기 위해 더 학습하거나 확인이 필요한 것.
- 모르는 것 1:
- 모르는 것 2:
- 확인 방법: <official-doc 다시 읽기 / 실 실험 / 멘토에게 질문>
## 답변 경계
> 어디까지 자신 있게 말할 수 있고, 어디부터는 "확인이 필요하다"라고 말해야 하는지.
- 자신 있게 말할 수 있는 범위:
- "이 부분은 공식 문서를 다시 보고 답변드리겠습니다" 라고 해야 하는 부분:
- **절대 과장하지 말 것** (예: 검증 안 된 prod 경험을 말하지 말 것):
## 관련
> 같은 작업 묶음 내 다른 raw 문서, 또는 같은 주제의 다른 면접 질문.
- 관련 면접 질문 (선행/후속): `[[raw/interviews/<...>]]`
- 영감을 받은 채용공고: `[[raw/job-postings/<...>]]`
- 관련 블로그 글감: `[[raw/blog-topics/<...>]]`
- 답변 derive 후 위치: `[[wiki/interview/<...>]]` (생성되면)
@@ -0,0 +1,68 @@
---
title:
source_type: interview
status: draft
confidence: unknown
tags: []
related_projects: []
last_reviewed:
---
# {{title}}
> Layer: `wiki/interview/` — 면접 답변용. 말로 했을 때 자연스럽게.
## 질문
면접에서 받을 가능성이 있는 질문 원형.
## 질문 의도
면접관이 이 질문으로 무엇을 평가하려는가.
## 짧은 답변 (30초)
핵심만 12문장.
## 상세 답변 (12분)
배경 → 핵심 개념 → 내 프로젝트 적용 → 결과/한계 순.
## 사실 / 추론 / 확인 필요
상세 답변에 들어간 진술을 3분류로 명시.
- **사실 (verified)** — canonical 문서에 `status: reviewed | verified | published-ready`이고 Sources가 있는 진술
- **추론 (inferred)** — canonical 내용을 조합한 결론. 면접 시 추론임을 드러내며 말할 것
- **확인 필요 (needs-confirmation)** — wiki에 없거나 stale, 또는 원천 status가 `draft` 이하. **면접 전에 raw 확인 또는 모른다고 답할 준비**
## 면접에서 말해도 되는 범위
- **자신 있게 답할 수 있는 부분** (`actually-implemented` / `locally-verified` / `prod-verified` 만):
- **모른다고 답해야 하는 부분** (`documented-only` / `planned` / `needs-confirmation`):
## 꼬리 질문
- 가능한 후속 질문 1 → 어떻게 답할지
- 가능한 후속 질문 2 → 어떻게 답할지
## 약한 답변 예시 (피해야 할 답)
- 답변 1: 왜 약한가
- 답변 2: 왜 약한가
## 과장 금지 지점
이 질문에 답할 때 **사실보다 부풀리기 쉬운 표현**.
## 근거 자료 (canonical 필수)
답변의 근거가 된 canonical wiki 문서. `wiki/concepts/` 또는 `wiki/projects/` **반드시 1개 이상**. status, confidence 함께 표기.
- `[[wiki/concepts/{{...}}]]` — status / confidence
- `[[wiki/projects/{{...}}]]` — status / confidence
## 관련 문서
- `[[{{관련-concept}}]]`
- `[[{{관련-project}}]]`
@@ -0,0 +1,51 @@
---
title:
source_type: invest-concept
status: draft
confidence: unknown
tags: [invest-concept, personal-invest, finance]
last_reviewed: YYYY-MM-DD
---
# {{title}}
> Layer: `wiki/invest-concepts/` — 검증된 투자 개념(ETF·금리·환율·분산 등). 내 전략 규칙은 `wiki/invest-strategy/`, 활성 계획은 `wiki/invest-plan/`.
## Parent
- `[[wiki/invest/invest-hub]]`
## Summary
한두 문장 핵심 정의.
## Standard (기준)
공식/학술 기준의 정의. 출처는 Sources 섹션.
## 한계 / 주의점
적용 한계·흔한 오해·트레이드오프. 검증된 것만 사실로, 그 외 `needs-confirmation`.
## Claim-backed Knowledge
> 핵심 설명은 raw 증거 claim으로 뒷받침.
| Knowledge Point | Supporting Claims | Confidence | Notes |
|---|---|---|---|
| <설명> | `raw/invest-research/<slug>.md#C1` | `high`/`medium`/`low` | |
## Strategy 연결
> 이 개념이 어떤 전략 규칙으로 연결되는지 링크.
- `[[wiki/invest-strategy/strategy]]` — <어느 규칙>
## Do Not Overclaim
이 개념을 말할 때 과장 금지 지점.
## 근거 자료
- [출처 제목](https://...) — 핵심
- `[[raw/invest-research/<...>]]` — 보존 원본
@@ -0,0 +1,67 @@
---
title: YYYY-MM-DD 투자 일일 조사
source_type: invest-daily
status: raw
confidence: unknown
tags: [invest-daily, personal-invest, macro]
date: YYYY-MM-DD
last_reviewed: YYYY-MM-DD
---
# YYYY-MM-DD 투자 일일 조사
> Layer: `raw/invest-daily/` — 그날의 거시 자금흐름 조사. **수치마다 출처 링크 + 조사 시점 필수**(실시간 아님). `/invest-ingest`가 검증 가능한 항목만 `wiki/invest-concepts/`로 추출. 원본은 raw에 영구 보관.
## Parent
> 이 노트가 속한 cluster 루트로 upward link (linking-rules).
- `[[wiki/invest/invest-hub]]`
## 고정 체크리스트 (매일 동일)
> 각 항목은 **수치 + 방향(↑/↓) + 출처 + 조사시점**. 모르면 비우되 추측 금지.
| 자산군 | 핵심 지표 | 값 / 방향 | 출처 | 조사시점 |
|---|---|---|---|---|
| 금리 | 미 10Y / 한 기준금리 | | | |
| 환율 | USD/KRW | | | |
| 원자재 | WTI / 금 | | | |
| 주요지수 | S&P500 / KOSPI / 나스닥 | | | |
| 코인 | BTC / ETH | | | |
## 오늘의 이슈 (가변)
> 그날 가장 큰 움직임·뉴스. 각 항목 출처 링크 필수.
- 이슈 1 — <한 줄> ([출처](https://...), 조사 YYYY-MM-DD)
## 관찰·가설 (미검증)
> 내 해석. **검증 전이므로 사실 아님.** canonical로 옮기기 전 `/invest-research`로 확인 대상.
- 가설 1:
## Promotable 후보
> `/invest-ingest`로 `wiki/invest-concepts/` 또는 `invest-strategy/`에 올릴 만한 것만 표기.
- 후보 1 (→ 어떤 canonical 문서로?)
## 분야 관찰
> 오늘 움직인 분야 카드와, 그 카드가 예측한 연결이 실측과 맞았는지 대조. 루프의 엔진 — 맞으면 `[가설]`→`[검증]` 승격 후보, 틀리면 새 학습거리. 카드 허브는 `[[wiki/invest-concepts/field-map]]`.
| 오늘 움직인 카드 | 방향 | 그 카드 예측 연결이 맞았나?(확인/반증) | 새 가설/메모 |
|---|---|---|---|
| `[[wiki/invest-concepts/field-dollar]]` | | | |
## 출처
> deep-research 가 조사한 **전(全) 출처**를 여기 남긴다 — "어디서 뭘 확인했나" 추적용. 각 줄에 `[primary/secondary/blog/unreliable]` 등급 + URL. 교차검증 실패(claims:0)·`[unreliable]` 출처도 *조사는 했으나 미채택* 기록으로 남겨 투명성 확보. 조사 통계(N각도·M출처·검증 confirmed/killed)도 1줄.
- (deep-research 채움 — 각도별/등급별로 전 출처 나열)
## Related
- 어제 노트: `[[raw/invest-daily/{{어제}}]]`
@@ -0,0 +1,65 @@
---
title:
source_type: invest-concept
status: draft
confidence: low
tags: [invest-concept, field-card, macro-asset]
last_reviewed: YYYY-MM-DD
---
# {{title}}
> Layer: `wiki/invest-concepts/` — 분야(자산군·섹터) 지식 카드. 노드 1장 = 분야 1개, 관계는 wikilink 엣지. **모든 관계 행에 `[검증]/[가설]` 라벨 필수.** `[가설]`은 외부 산출물 사용 금지(파생 규칙). 세무·투자 자문 아님 — `[[wiki/invest-strategy/strategy]]` §고지.
## Parent
- `[[wiki/invest-concepts/field-map]]`
## 한 줄 정의
> 이 분야가 뭔지 한 문장.
## 무엇이 이걸 움직이나
> 이 분야를 위/아래로 미는 입력 요인. 각 행에 `[검증]/[가설]` + 근거.
| 요인 | 방향 | 메커니즘 | 검증/가설 | 근거 |
|---|---|---|---|---|
## 연결
> ★ 엣지 — 이게 움직이면 *따라오는* 것. 다른 카드로 wikilink 연결.
| 이게 ↑하면 | → 따라 | 메커니즘 | 검증/가설 | 근거 |
|---|---|---|---|---|
## 대장주 / 추종주 (Leaders & Followers)
> (산업 섹터 카드에만 — 자산군 카드는 생략 가능) 대장주(선행·시총/거래 주도)와 따라 움직이는 추종주. 대장주가 움직이면 추종주를 본다. **종목 선정·동조 관계는 전부 `[가설]`** — `/invest-research`로 검증.
| 종목(티커) | 역할 | 왜(동조 근거) | 검증/가설 |
|---|---|---|---|
## 관찰 지표
> 이 분야 상태를 매일 보는 구체 지표·티커(invest-daily가 잡을 것).
-
## 경기 사이클 위치
- 회복/확장/둔화/침체 중 언제 강·약
## 검증 상태
- `[검증]` N개 · `[가설]` M개 (관찰 누적 → `/invest-research`로 승격)
## 근거 자료
- `[[wiki/invest-strategy/strategy]]`
## Related
> 연결된 카드(= 그래프 엣지).
-
@@ -0,0 +1,46 @@
---
title: 매매 원장 / Trade Ledger
source_type: invest-ledger
status: raw
confidence: unknown
tags: [invest-ledger, personal-invest, finance]
created: YYYY-MM-DD
last_reviewed: YYYY-MM-DD
---
# 매매 원장
> Layer: `raw/invest-ledger/` — 실제 매수/매도의 **사실 기록**. 단일 원장 파일에 모든 거래를 누적(설계 §8-3). `/invest-decide`가 행을 추가하며 `wiki/invest-strategy/`의 규칙 위반을 체크. wiki로 옮기지 않음.
## Parent
- `[[wiki/invest/invest-hub]]`
## 현재 포지션
| 종목/티커 | 분류(코어/베팅) | 보유수량 | 평균단가 | 현재 비중% | 메모 |
|---|---|---|---|---|---|
## 거래 내역
> 시간 역순(최신 위). 모든 행은 근거 문서 링크 필수.
> ⚠️ **실손익 = (단가×수량) − 수수료 ± 환차손익 − 세금.** 해외상장 ETF는 **양도세(연 250만 공제 후 22%, 손익통산)** + **체결 환율** 이 손익에 실질적 영향 → 아래 컬럼에 기록. 국내상장 ETF/주식은 세제가 다름(증권거래세·배당소득세).
| 날짜 | 매수/매도 | 종목 | 수량 | 단가 | 수수료 | 체결환율 | 금액(원) | 계좌 | 근거(링크) | 규칙체크 |
|---|---|---|---|---|---|---|---|---|---|---|
## 규칙 위반 이력
> `/invest-decide`가 빨간 플래그를 낸 건 기록. 무시하고 진행했다면 그 사유도.
| 날짜 | 위반 규칙 | 내용 | 사용자 처리 |
|---|---|---|---|
## 손익 요약
> `/invest-review` 실행 시 갱신.
- 총 투입원금:
- 평가금액:
- 실현손익:
- 목표 대비:
@@ -0,0 +1,100 @@
---
title:
source_type: invest-plan
status: draft
confidence: unknown
tags: [invest-plan, personal-invest, finance]
last_reviewed: YYYY-MM-DD
---
# {{title}}
> Layer: `wiki/invest-plan/` — 현재 활성 투자 계획. `wiki/invest-strategy/` 규칙 + 최근 `raw/invest-research/`·`raw/invest-daily/` 조사에서 도출. **모든 항목은 canonical/증거 근거 링크 필수.**
> ⚠️ 면허 자문 아님 — `[[wiki/invest-strategy/strategy]]` §고지 참조.
> 📐 **이 템플릿의 목적 = 구체성 강제.** "광범위 ETF를 산다" 수준이 아니라 *어떤 종목을·얼마를·언제·어느 계좌에서·자본이 커지면 어떻게 바꾸는가*까지 박는다. 비어 있으면 `NEEDS_DECISION` 라벨.
## Parent
- `[[wiki/invest/invest-hub]]`
## 현재 자본·목표·계좌
> strategy 프로필에서 끌어온 기준점. 한 줄씩 *구체 숫자*로.
- 가용 자본: **{{원금}}** ({{여유자금 여부·출처}})
- **현재 자본 구간**: {{strategy ① 구간 매핑 — 예: ~200만 이하}} → 기본 전략 {{예: 광범위 ETF 1~2개}}
- MDD 수용 / 주식 비중: **{{예: ~-40% / 주식 90~100%}}** (`[[wiki/invest-strategy/strategy]]` 프로필)
- 계좌: **{{예: 일반 위탁계좌}}** ({{근거 링크}})
- 매수 방식: **{{일시매수 | 분할(DCA) N회}}** ({{근거 — strategy ⑤}})
- 이번 분기 목표: {{고정 목표금액 없음이면 그렇게 — 분기는 "정산" 아니라 "점검"}}
## 목표 자산 배분
| 자산 | 분류(코어/완충/베팅) | 목표 비중% | 근거(링크) |
|---|---|---|---|
| {{광범위 주식 ETF}} | 코어 | {{%}} | {{strategy ① / invest-research}} |
| {{현금 완충}} | 완충 | {{%}} | {{심리·리밸런스 — UNSUPPORTED_IMPL_DECISION이면 표기}} |
## 보유 종목
> 실제 보유 현황. `[[raw/invest-ledger/ledger]]`와 동기화(원장이 사실 SSOT, 여기는 목표 대비 현황). 매수 전이면 "없음".
| 종목/티커 | 분류 | 보유수량 | 평단 | 현재 비중% | 목표 비중% | 근거(링크) |
|---|---|---|---|---|---|---|
| {{미정이면 — 4단계서 확정}} | | | | | | |
## 매수 실행
> **무엇을·얼마를·언제·어느 계좌에서.** 이 § 가 비면 "내일 뭘 누를지" 답이 없는 것.
- **무엇을 (종목)**: {{구체 티커 1개 — 미정이면 `NEEDS_DECISION` + 좁히는 invest-research 링크}}
- **얼마를 (금액)**: {{예: 100만 일시 / 25만×4회}}
- **언제·어떻게 (스케줄)**: {{일시매수면 "1회" / 분할이면 주기·간격 표}}
- **다음 매수 트리거**: {{추가납입 시점 — 소득 발생 / 정기 / 자본 구간 전환}}
- **매수 후**: `/invest-decide``[[raw/invest-ledger/ledger]]`에 기록(규칙 위반 자동 체크).
## 자본 성장 로드맵
> "100만으로 시작해 키운다"의 *체계*. strategy ① 자본 구간 규칙 + ④ 절세계좌 조건을 단계로 펼침. **각 단계 전환은 자본 임계치 / 소득 발생 같은 명시적 트리거로.**
| 단계 | 자본 구간 | 전략 (strategy ① 매핑) | 계좌·절세 (strategy ④) | 전환 트리거 |
|---|---|---|---|---|
| **현재** {{▶ 표시}} | {{~200만}} | {{광범위 ETF 1~2개}} | {{일반계좌, 절세계좌 보류}} | — |
| 다음 | {{200~1,000만}} | {{ETF 코어 + 위성 1~2}} | {{소득 발생 시 ISA/연금 재검토}} | {{자본 200만 돌파 OR 소득 발생}} |
| 그다음 | {{1,000만~}} | {{자산군 배분 본격화}} | {{}} | {{자본 1,000만 돌파}} |
- **소득 발생 시 (별도 트리거)**: ① 월 추가납입 시작 → 매수 실행 § 갱신, ② **절세계좌 재검토** — 결정세액 생기면 ISA 손익통산·연금 세액공제 가치 발생(`[[raw/invest-research/2026-06-08-isa-vs-general-account-no-income]]` 무소득 시 실익 없음 결론이 뒤집힘), ③ MDD·목표 재설정 가능.
## 리밸런싱·점검 규칙
> 언제·무엇을 점검하나. `/invest-review`가 이 규칙으로 돈다.
- **점검 주기**: {{예: 분기 1회}}. 분기말 하락장이어도 강제매도 ❌ (strategy ②).
- **리밸런싱 밴드**: 목표 배분 **±5%p** 이탈 시 검토 (strategy ①, 재량 — 잦은 매매 경계).
- **점검 체크리스트**: ① 비중 drift ② stale 조사(90일+) ③ 규칙 위반 매매 ④ 자본 구간 전환 도달 여부.
## 워치리스트
| 종목/티커(유형) | 왜 후보인가 | 검증 상태(invest-research 링크) | 진입 조건 |
|---|---|---|---|
## 리스크·한계
- 이 계획이 틀릴 수 있는 지점: {{단일 최대 전제부터}}
- 말하면 안 되는 범위(검증 안 된 것): {{미검증·기각 claim}}
## 규칙 사전 점검 (Rule Pre-check)
> 계획이 strategy ①~⑤를 위반하지 않는지. 위반 시 플래그.
- ① 포지션 크기: {{}} → 준수/위반
- ② 손절/익절: {{}} → 준수/위반
- ③ 행동 가드레일: {{}} → 준수/위반
- ④ 절세계좌: {{}} → 준수/위반
- 위반: {{없음 / 목록}}
## 근거 자료
- `[[wiki/invest-strategy/strategy]]`
- `[[raw/invest-research/<...>]]`
- `[[raw/invest-daily/<...>]]`
@@ -0,0 +1,60 @@
---
title:
source_type: invest-research
status: raw
confidence: unknown
url:
archive_url:
tags: [invest-research, personal-invest, finance]
created: YYYY-MM-DD
last_reviewed: YYYY-MM-DD
---
# {{title}}
> Layer: `raw/invest-research/` — 특정 분야/자산/주장에 대한 심층 조사. **외부 출처의 verbatim 인용 보존**(evidence-first-research). 검증된 결론만 `/invest-ingest`로 `wiki/invest-concepts/` 또는 `invest-strategy/`로 추출.
## Parent
- `[[wiki/invest/invest-hub]]`
## 조사 질문
> 무엇을 확인하려고 조사했는가 1~2줄.
## 출처
| # | 제목 | 출처 등급 | URL | 발행/조사일 |
|---|---|---|---|---|
| S1 | | official / vendor-research / academic / media / blog(약함) | | |
## 핵심 인용
> 원문 그대로. 출처 # 표기. 의역 금지.
> [S1] "원문 발췌 1."
## 추출된 주장
> 출처가 **직접 말하는 것만**. 내 적용 결론은 여기 쓰지 않음. Claim ID는 문서 내 안정 유지.
| Claim ID | Claim | Evidence quote | Strength | 적용 조건 | 증명 못 하는 것 |
|---|---|---|---|---|---|
| C1 | | [S1] "<인용>" | academic / official / vendor-research / media / needs-confirmation | | |
## 판정
> 각 Claim에 대한 KEEP / CORRECT / REJECT + 한 줄 사유.
- C1: KEEP — <사유>
## 적용 경계
- 직접 증명하는 것:
- 증명하지 않는 것:
- 내 상황(소액·국내 거주)에 적용하려면 추가 확인할 것:
## Related
- 같은 주제 다른 조사: `[[raw/invest-research/<...>]]`
- 이 조사를 인용한 canonical: `[[wiki/invest-strategy/strategy]]` (생성 시)
@@ -0,0 +1,65 @@
---
title:
source_type: invest-strategy
status: draft
confidence: unknown
tags: [invest-strategy, personal-invest, finance]
last_reviewed: YYYY-MM-DD
---
# {{title}}
> Layer: `wiki/invest-strategy/` — 내 투자 전략 규칙. `/invest-decide`가 이 문서의 고정 규칙과 매매를 대조한다.
## ⚠️ 고지 (Disclaimer)
> **면허 있는 투자자문이 아님.** Claude는 환각으로 틀릴 수 있고 손실에 책임지지 않는다. 모든 수치는 조사 시점 기준이며 본인이 출처로 교차검증한다. 이 시스템은 "규율 강제 + 리서치 보조"이지 자산관리사가 아니다.
## Parent
- `[[wiki/invest/invest-hub]]`
## 내 프로필 (규칙 기준점)
- 시작 자본:
- 목표 금액 / 기간:
- 월 추가납입:
- 최대 감내손실(MDD):
- **현재 과세소득(결정세액) 유무:** <있음/없음/미확인 — 절세계좌 규칙이 의존. 미확인 시 연금계좌 권고 보류>
## ① 포지션 크기 규칙 (자본 구간별)
| 자본 구간 | 기본 전략 | 근거 |
|---|---|---|
## 익절 규칙
- 코어(광범위 ETF):
- 개별 베팅: <두면 `UNSUPPORTED_DECISION` 라벨 + "근거 아닌 재량" 명시>
## ③ 행동 가드레일
- 패닉셀 쿨다운:
- FOMO 가드:
- 거래 빈도 상한:
- 선근거 원칙:
## ④ 절세계좌 우선순위 (조건부)
- 사전 체크:
- 계좌별 한도(연도 명시):
## ⑤ 목표·금액
- (위 프로필과 연결)
## 규칙 근거
> 각 규칙이 어느 증거에서 도출됐는지. 근거 없는 규칙은 `UNSUPPORTED_DECISION` 라벨.
| 규칙 | Supporting Claim | 판정 |
|---|---|---|
## 근거 자료
- `[[raw/invest-research/<...>]]`
@@ -0,0 +1,98 @@
---
title: job-posting / {{company}}-{{role-slug}}
source_type: job-posting
status: raw
related_branches: []
related_projects: []
tags: [job-posting]
created: YYYY-MM-DD
posting_url:
archive_url:
status_label: collected
---
# job-posting: {{company}} — {{role}}
> Layer: `raw/job-postings/` — 채용공고 **원본 수집·블로그 글감 추출**. 다듬어진 블로그 초안은 `/blogify` 후 `wiki/blog/`에 별도 작성. 원본은 raw에 영구 보관.
> `status_label`: `collected` | `analyzed` | `topics-extracted` | `derived-to-blog` | `passed-on`
## 부모
> 이 채용공고가 어느 작업·프로젝트와 연결되는지. **최소 1개 필수.** 특정 작업과 무관한 일반 시장 조사면 `[[raw/project-notes/<project>]]` (커리어 메인 프로젝트) 로 연결.
- `[[raw/branch-notes/{{branch-name}}]]` — <어떤 작업과 연관된 채용 요건인지>
- (또는) `[[raw/project-notes/{{project-name}}]]`
## 채용공고 출처
- 회사: {{company}}
- 역할: {{role}}
- 공고 URL: <원본 URL>
- 아카이브 URL:
- 수집 날짜: YYYY-MM-DD
- 마감 (있다면):
## 요구 사항
> 공고에서 직접 인용. 자기 해석 추가하지 말 것. 해석은 §분석에 별도.
- 필수 (Required):
- <원문 인용 1>
- <원문 인용 2>
- 우대 (Preferred):
- <원문 인용 1>
- <원문 인용 2>
## 분석
> 위 원문에 대한 내 해석. 사실과 분리.
### 내가 이미 갖춘 것
- <항목> — 근거: `[[raw/branch-notes/<...>]]` 또는 `[[wiki/projects/<...>]]`
### 부족한 것
- <항목> — 학습 계획: <어떻게 보강할지>
### 흥미로운 신호
- <기술 스택이나 키워드 중 처음 보는 것 / 트렌드 신호>
## 블로그 글감
> 이 공고가 자극한 글감. wiki/blog/ 초안 후보가 됨.
- 글감 1: <한 문장 요지>
- 타깃 독자:
- 인용할 raw 자료: `[[raw/official-docs/<...>]]`, `[[raw/branch-notes/<...>]]`
- 예상 derived 위치: `[[wiki/blog/<slug>]]`
- 글감 2: ...
## 면접 글감
> 이 공고가 자극한 면접 질문 후보. raw/interviews/로 분리해 별도 노트 만들지 결정.
- 예상 질문 1 — 후속 raw 노트: `[[raw/interviews/<...>]]` (생성 시)
- 예상 질문 2: ...
## 근거 자료
> 공고 평가 또는 글감 작성에 인용된 자료.
- `[[raw/official-docs/<...>]]`
- `[[raw/company-tech-blogs/<...>]]`
## 결정
> 이 공고에 대한 액션. 면접 준비 / 블로그 초안 작성 / 패스 / 보관만.
- 액션: `apply` | `prep-only` | `blog-only` | `pass-but-archive`
- 이유 (1~2줄):
## 관련
- 같은 회사 다른 공고: `[[raw/job-postings/<...>]]`
- 유사 역할 다른 공고: `[[raw/job-postings/<...>]]`
- 파생된 블로그: `[[wiki/blog/<...>]]`
- 파생된 면접 노트: `[[raw/interviews/<...>]]`
@@ -0,0 +1,91 @@
---
title: lecture / {{course-slug}}-{{episode-or-topic}}
source_type: lecture
status: raw
related_branches: []
related_projects: []
tags: [lecture]
created: YYYY-MM-DD
course:
instructor:
episode:
duration:
url:
archive_url:
status_label: in-progress
---
# lecture: {{course}} — {{episode-or-topic}}
> Layer: `raw/lectures/` — 강의·강연·컨퍼런스 발표의 **원본 발췌 + 학습 메모**. 검증된 개념 요약은 `/ingest` 후 `wiki/concepts/`에 `source-summary-template` 형식으로 별도 작성. 원본은 raw에 영구 보관.
> `status_label`: `in-progress` | `done` | `reviewed` | `concepts-extracted` | `needs-confirmation`
## 부모
> 이 강의를 들은 동기. **최소 1개 필수.** 특정 작업을 위한 학습이면 branch, 프로젝트 차원 일반 학습이면 project.
- `[[raw/branch-notes/{{branch-name}}]]` — <어떤 작업을 위해 이 강의를 학습>
- (또는) `[[raw/project-notes/{{project-name}}]]` — <전체 프로젝트 차원 학습>
## 강의 출처
- 코스 / 강연: {{course}}
- 강사 / 발표자: {{instructor}}
- 에피소드 / 챕터: {{episode}}
- 길이: {{duration}}
- URL: <강의 URL>
- 아카이브 URL:
- 시청 날짜: YYYY-MM-DD
## 왜 들었는지
> 이 강의를 본 이유. 어떤 문제·궁금증·작업과 연결되는가.
<1~2줄>
## 핵심 인용
> 강사의 발언을 그대로. 자기 해석 추가하지 말 것 (별도 § 학습 메모).
- [HH:MM:SS] "<verbatim 발췌 1>"
- [HH:MM:SS] "<verbatim 발췌 2>"
- [HH:MM:SS] "<verbatim 발췌 3>"
## 핵심 개념
> 강의에서 다룬 개념의 raw 정리. 이 단계는 자기 이해 수준의 메모. 검증된 정의는 wiki/concepts로 옮길 때 만듦.
- 개념 1:
- 강사의 설명 (요약):
- 내 이해 (자신 없으면 `needs-confirmation`):
- 인접 개념:
- 개념 2: ...
## 학습 메모
> 강의를 들으며 떠오른 생각·연결·반론. 강사의 사실과 분리.
- 내 프로젝트와의 연결: `[[raw/branch-notes/<...>]]`
- 강사 의견과 다른 점이 있다면:
- 추가 확인이 필요한 것:
## 보강 자료
> 강의 외에 같이 본 공식 문서·블로그.
- `[[raw/official-docs/<...>]]` — <어떤 부분을 보강하는지>
- `[[raw/company-tech-blogs/<...>]]`
## 작업 항목
> 이 강의 결과 해야 할 일.
- [ ] 관련 branch에서 실험 해보기 — `[[raw/branch-notes/<...>]]`
- [ ] wiki/concepts/ 로 추출할 개념: <개념 슬러그>
- [ ] 후속 강의·문서: <다음에 볼 자료>
## 관련
- 같은 코스 다른 에피소드: `[[raw/lectures/<...>]]`
- 유사 주제 다른 강의: `[[raw/lectures/<...>]]`
- 파생된 wiki 개념: `[[wiki/concepts/<...>]]` (생성 시)
@@ -0,0 +1,118 @@
---
title:
source_type: portfolio
status: draft
confidence: unknown
tags: [portfolio]
related_projects: []
last_reviewed:
canonical_sources: []
audience: recruiter
---
# {{title}}
> Layer: `wiki/portfolio/` — **외부 공개용 프로젝트 요약**. canonical (`wiki/projects/`) 에서 파생된 산출물. 면접관·이력서 reader·포트폴리오 사이트 대상.
> 상태: draft → reviewed → verified → **published-ready** (이력서·README·외부 게시 가능)
> `audience`: `recruiter` | `tech-lead` | `cs-interviewer` | `general` — 톤·깊이가 달라짐.
## 부모 (필수)
> wiki/portfolio/ 는 derived layer. **반드시 canonical wiki/projects/ 에서 파생.** raw 또는 branch에서 직접 파생 금지.
- `[[wiki/projects/{{project-slug}}]]` (필수, 최소 1개)
- 추가 wiki/projects 인용:
- `[[wiki/projects/<...>]]`
- 보조 wiki/concepts:
- `[[wiki/concepts/<...>]]`
## 한 줄 요약
> 30초 자기소개 한 줄. 무엇을 했고 왜 그 가치가 있는지.
<한 줄>
## 문제
> 이 프로젝트가 해결한 문제. 추상적 표현 금지 — 구체 수치·시나리오로.
- 직면한 문제:
- 영향 범위:
- 측정 가능한 손실 (있다면 — latency / 비용 / 사고 빈도):
## 해결
> 이 프로젝트에서 한 핵심 결정 3~5개. 트레이드오프와 함께.
- 결정 1: <무엇을> — 이유: <왜> — 트레이드오프: <대안 대비 손해 본 것>
- 결정 2: ...
- 결정 3: ...
## 결과
> 측정 가능한 결과만. 짐작·과장 금지. 측정 안 한 것은 "측정 X"로 명시.
- 측정 1 (자동화·테스트·로그): <before → after>
- 측정 2 (운영 기록·인시던트 빈도): <before → after>
- 측정 안 한 것: <항목>
## 기술 스택
> 실제 사용한 것만. "쓸 줄 안다" 와 "이 프로젝트에 썼다" 를 구분.
- 핵심: <Java 21, Spring Boot 3.4, ...>
- 보조: <...>
- 의식적으로 안 쓴 것 (있으면 면접 차별화): <...>
## 익혀야 할 것
> 면접관·리뷰어가 이 포트폴리오를 읽고 "이 분야를 안다"고 판단할 수 있는 항목. 자기 학습 가이드 역할도 함.
- 익혀서 자신 있게 답할 수 있어야 할 개념: `[[wiki/concepts/<...>]]`
- 실제 구현 결정에 대해 변호할 수 있어야 함: `[[wiki/projects/<...>]]`
- 인용한 출처를 자신 있게 인용 가능해야 함: `[[raw/official-docs/<...>]]`, `[[raw/company-tech-blogs/<...>]]`
## 답할 수 있는 범위
> 면접에서 자신 있게 답할 수 있는 부분 / "확인이 필요하다"라고 말해야 하는 부분 명시.
- 자신 있게 답할 수 있는 범위:
- "공식 문서를 다시 확인하고 답변드리겠습니다" 라고 해야 하는 부분:
- 절대 과장하지 말 것 (예: 검증 안 된 prod 경험을 prod-verified로 말하지 말 것):
## 한계
> 이 프로젝트가 못 한 것. 솔직하게.
- 검증 안 한 영역:
- 시간 부족으로 미룬 것:
- 알면서 안 한 결정 (트레이드오프):
## 근거 (canonical 인용 필수)
> derived 산출물의 모든 사실 주장은 canonical 인용으로 뒷받침.
- `[[wiki/projects/<...>]]` — <어떤 결정의 출처>
- `[[wiki/concepts/<...>]]` — <어떤 개념의 출처>
## 외부 링크
- GitHub 저장소:
- 데모:
- 관련 블로그 글: `[[wiki/blog/<...>]]`
## 관련
- 다른 포트폴리오 항목: `[[wiki/portfolio/<...>]]`
- 관련 면접 답변: `[[wiki/interview/<...>]]`
- 관련 블로그 글: `[[wiki/blog/<...>]]`
## 게시 체크리스트
`published-ready` 로 올리기 전 확인.
- [ ] 모든 측정값이 실측이거나 "측정 X" 로 명시됨
- [ ] 과장 단어 (`완벽`, `극한`, `100%`, `최고`) 없음
- [ ] 모든 사실 주장에 canonical 링크 있음
- [ ] 답할 수 있는 범위 / 한계 섹션 채움
- [ ] `/lint` 통과
@@ -0,0 +1,279 @@
---
title: ""
source_type: "report"
status: "draft"
confidence: "unknown"
derived_from:
- "wiki/projects/<canonical-project-doc>"
- "raw/branch-notes/<optional-branch-note>"
related_projects:
- "ca-tmpl"
audience: "self"
purpose: "big-picture-understanding"
last_reviewed: ""
status_label: "draft"
---
# {{title}}
> 이 문서는 이해를 위한 derived report입니다.
> SSOT는 `raw/branch-notes/`와 `wiki/projects/`의 canonical 문서입니다.
> 이 문서는 ca-tmpl 전체 구조를 사람이 읽고 설명할 수 있도록 재구성합니다.
---
## 0. Reading Guide
### 이 문서는 무엇을 설명하는가
`<ca-tmpl 전체 구조, 목표, 핵심 계약, 구현 상태를 설명한다.>`
### 먼저 읽어야 할 사람
- `<ca-tmpl의 큰 그림이 아직 안 잡힌 사람>`
- `<branch-note를 읽기 전에 전체 지도가 필요한 사람>`
- `<Clean Architecture skeleton의 운영 계약이 왜 필요한지 이해하려는 사람>`
### 이 문서를 읽고 답할 수 있어야 하는 질문
- ca-tmpl은 무엇인가?
- 왜 도메인 기능을 제거했는가?
- 왜 운영 계약이 skeleton의 중심인가?
- 왜 branch-note가 많은가?
- 각 branch-note는 전체 skeleton의 어느 영역을 책임지는가?
- 현재 구현된 것과 아직 문서만 있는 것은 무엇인가?
### SSOT
- Canonical:
- `wiki/projects/<canonical-project-doc>`
- Raw / branch notes:
- `raw/branch-notes/<optional-branch-note>`
### 이 문서의 한계
- 이 문서는 SSOT가 아니다.
- 구현 상태는 작성일 기준이다.
- 세부 결정은 각 branch-note와 canonical 문서를 확인해야 한다.
---
## 1. 이 프로젝트는 무엇인가
### 한 문장 정의
> ca-tmpl은 `<새 백엔드 프로젝트를 시작할 때 반복적으로 필요한 운영 계약>`을 Clean Architecture 구조로 미리 고정해두는 skeleton이다.
### 하지 않는 것
- 특정 비즈니스 도메인을 제공하지 않는다.
- 특정 adapter를 무겁게 기본 탑재하지 않는다.
- raw branch-note에서 곧바로 blog/interview/portfolio로 파생하지 않는다.
- 운영 실패, 로그, trace, API envelope, module boundary를 프로젝트마다 임의로 재결정하지 않는다.
### 제공하는 것
- module/package boundary
- structured API response
- operational error category
- exception ownership
- boundary validation / mapper contract
- structured logging / tracing
- env-driven runtime configuration
- repository capability contract
- adapter failure mapping
- architecture test / contract test
- sample domain fixture
### 왜 skeleton인가
`<도메인 기능 자체보다, 도메인을 얹었을 때 동일한 운영 계약과 아키텍처 경계를 유지하는 구조가 목적이기 때문이다.>`
---
## 2. 이 프로젝트가 해결하는 핵심 문제
### 문제 1. 프로젝트마다 실패 처리 방식이 달라지는 문제
- 어떤 프로젝트는 validation 실패를 400으로 반환한다.
- 어떤 프로젝트는 같은 실패를 500으로 반환한다.
- 어떤 프로젝트는 raw exception message를 client에게 노출한다.
- 결과적으로 운영, 디버깅, API contract가 흔들린다.
### 문제 2. Clean Architecture 경계가 문서에만 남고 코드에서 무너지는 문제
- controller가 JPA entity를 직접 반환한다.
- application layer가 Spring/JPA 구현체를 직접 import한다.
- domain이 framework annotation을 알게 된다.
- adapter끼리 직접 참조하면서 순환 결합이 생긴다.
### 문제 3. 관측성 정보가 일관되지 않은 문제
- requestId가 없는 로그가 남는다.
- traceId와 correlationId 의미가 branch마다 다르다.
- 장애 발생 시 어떤 요청에서 어떤 dependency 실패가 났는지 추적하기 어렵다.
### 문제 4. 테스트가 구현 세부만 검증하고 계약 위반을 잡지 못하는 문제
- unit test는 통과하지만 architecture boundary가 깨진다.
- API response schema drift가 생겨도 release 전에 감지하지 못한다.
- contract violation이 warning-only로 남는다.
---
## 3. 전체 구조 요약
| 영역 | 역할 | 왜 필요한가 |
| ------------------- | --------------------------------------------------- | --------------------------------------------------- |
| domain-core | 순수 domain model, value object, domain rule | framework와 adapter로부터 business invariant를 보호 |
| application-core | use case, command/query, port, policy validation | business flow와 외부 구현체 사이의 경계 유지 |
| adapter-web | HTTP DTO, controller, validation, response mapper | 외부 HTTP 요청을 application contract로 변환 |
| adapter-persistence | JPA/RDBMS 저장소 구현, entity, mapper | persistence 기술을 application port 뒤로 숨김 |
| adapter-outbound | HTTP client, messaging, cache, notification adapter | 외부 dependency 세부 구현을 격리 |
| shared-contract | envelope, error code, header/log/metric registry | skeleton-wide operational contract 공유 |
| app-bootstrap | Spring Boot entrypoint, DI wiring, runtime config | composition root로 runtime module을 조립 |
| sample-portfolio | skeleton contract 검증용 fixture | 실제 domain 없이 contract를 검증 |
---
## 4. 핵심 흐름
### 4.1 Request 처리 흐름
```text
HTTP Request
→ adapter-web Request DTO
→ request validation
→ mapper
→ application Command/Query
→ use case
→ domain model / domain rule
→ output port
→ adapter-persistence or adapter-outbound
→ response mapper
→ structured envelope
```
### 4.2 Error 처리 흐름
```text
Exception or failure
→ layer-specific exception ownership
→ operational error mapping
→ error.code / error.category / retryable
→ structured envelope
→ structured log
→ trace correlation
```
### 4.3 Domain Feature 추가 흐름
```text
presentation request/response DTO
→ request mapper
→ application command/query
→ use case
→ input port / output port
→ domain model / value object / domain rule
→ persistence model / repository adapter
→ response mapper
→ contract test
→ architecture rule
```
---
## 5. 주요 계약 묶음
| 계약 영역 | 담당 branch | 설명 | 현재 상태 |
| ---------------------------- | -------------------------- | ---------------------------------------------- | ---------- |
| error / observability | `raw/branch-notes/<...>` | error category, envelope, log/trace 기반 | `<status>` |
| API contract | `raw/branch-notes/<...>` | versioning, pagination, headers, idempotency | `<status>` |
| boundary validation / mapper | `raw/branch-notes/<...>` | DTO → command/query → domain 변환 경계 | `<status>` |
| module/package blueprint | `raw/branch-notes/<...>` | Gradle multi-module, package responsibility | `<status>` |
| transaction / concurrency | `raw/branch-notes/<...>` | transaction boundary, lock, retry, idempotency | `<status>` |
| sample fixture | `raw/branch-notes/<...>` | skeleton contract 검증용 sample domain | `<status>` |
| architecture enforcement | `raw/branch-notes/<...>` | ArchUnit / Gradle dependency guardrail | `<status>` |
---
## 6. 현재 구현 상태
| 영역 | 상태 | 근거 | 남은 위험 |
| -------- | ------------------------------------------------------------------------ | -------------------- | --------- |
| `<영역>` | `<decision-only / documented-only / local-verified / pending / unknown>` | `<문서/코드/테스트>` | `<위험>` |
### 상태 값 정의
| 상태 | 의미 |
| --------------- | ----------------------------------- |
| decision-only | 결정은 있으나 구현/검증은 아직 없음 |
| documented-only | 문서상 계약만 있음 |
| local-verified | 로컬 코드/테스트로 검증됨 |
| pending | 아직 착수 전 또는 잔여 작업 존재 |
| unknown | 근거 부족으로 판단 불가 |
---
## 7. 큰 그림에서 가장 중요한 설계 판단
### 판단 1. `<판단 이름>`
- 결정:
- 이유:
- 대안:
- 선택하지 않은 이유:
- 근거:
- 남은 리스크:
### 판단 2. `<판단 이름>`
- 결정:
- 이유:
- 대안:
- 선택하지 않은 이유:
- 근거:
- 남은 리스크:
---
## 8. 내가 설명할 수 있어야 하는 문장
### 30초 설명
`<ca-tmpl을 30초 안에 설명하는 문장>`
### 2분 설명
`<면접/리뷰/동료 설명에서 말할 수 있는 설명>`
### 깊게 질문받았을 때
**Q. 왜 도메인 기능을 제거했나?**
A. `<답변>`
**Q. 왜 sample-portfolio가 필요한가?**
A. `<답변>`
**Q. 왜 shared-contract가 필요한가?**
A. `<답변>`
**Q. 왜 architecture test가 필요한가?**
A. `<답변>`
---
## 9. 아직 이해가 부족한 부분
| 질문 | 왜 헷갈리는가 | 확인할 문서 | 확인할 코드 |
| ---- | ------------- | ----------- | ----------- |
| | | | |
---
## 10. 다음에 읽을 문서
- `wiki/reports/ca-tmpl/01-module-boundary-report`
- `wiki/reports/ca-tmpl/02-operational-error-observability-report`
- `wiki/reports/ca-tmpl/03-api-contract-report`
- `wiki/reports/ca-tmpl/04-boundary-validation-mapper-report`
@@ -0,0 +1,468 @@
---
title:
source_type: project-note
status: draft
confidence: unknown
tags: [project-note]
related_projects: []
last_reviewed:
diagrams: []
architecture_review:
status_label: active
project_revision: 1
---
# {{title}}
> Layer: `raw/project-notes/` (primary, hub) → `/ingest` 후 검증된 사실은 `wiki/projects/` 로 추출.
> 본 문서는 **프로젝트의 최상위 hub**. 프로젝트 전체 컨텍스트 / 문제 정의 / 시스템 아키텍처 / 핵심 시퀀스가 여기에 집중. 모든 branch / errors / interviews / lectures / job-postings / blog-topics / sources 가 본 문서로 upward link.
> `status_label`: `active` | `paused` | `completed` | `archived`
> `project_revision`: project decision/work-item snapshot 의 양의 정수 revision. 레지스트리의 의미가 바뀌면 증가시킨다.
## 1. 프로젝트 개요
> 외부인이 1분 안에 "이게 뭐 하는 프로젝트인가" 이해할 수 있어야 함.
- **한 줄 요약**: <무엇을 / 왜 / 누구를 위해>
- **기간**: <시작 ~ 종료(또는 in-progress)>
- **현재 상태**: `active` | `paused` | `completed` | `archived`
- **나의 역할 / Role**: <구현자 / 설계자 / 학습자 / 컨설팅 / 팀원 등>
- **저장소 / Repo**:
- 메인: `<git url>`
- 부속:
## 2. 문제 정의
> 추상화 금지. 구체 시나리오·수치로.
### 2.1 현재 상태의 문제
- 문제 1: <구체적 통증>
- 문제 2:
- 문제 3:
### 2.2 왜 지금 해결해야 하는가
- 트리거 (왜 지금):
- 비용 (해결 안 했을 때 손실):
- 기회 (해결 시 가치):
### 2.3 성공 기준
> 측정 가능해야 함. "잘 동작한다" 같은 모호 표현 금지.
- 기준 1: <측정 가능한 결과>
- 기준 2:
- 기준 3:
## 3. 시스템 아키텍처
> **필수 섹션.** 아키텍처 다이어그램이 없는 project-note 는 hub 역할을 못 함.
### Diagram tool 선택 — 엄격한 분리
| 다이어그램 종류 | 도구 | 이유 |
|---|---|---|
| **시스템 아키텍처 / 컴포넌트 구성도 / 배포 토폴로지 / 데이터 흐름 (정적 구조)** | **draw.io XML (`.drawio` 또는 `.drawio.svg`)** | 자유 배치 / 시각적 그룹화 / 신뢰 경계 / 색상 코딩 / Obsidian draw.io 플러그인 native 편집 |
| **시퀀스 다이어그램** | **Mermaid `sequenceDiagram`** | 텍스트 기반·git diff 친화, 시간축 표현에 최적 |
| **ER 다이어그램 (데이터 모델, 선택)** | **Mermaid `erDiagram`** | 텍스트 기반·관계 카디널리티 표기 직관적 |
| 작은 결정 트리 / 짧은 플로우차트 | Mermaid `flowchart` 도 허용 (작은 규모 한정) | 시퀀스가 아닌 단순 분기 |
**금지**:
- 시스템 아키텍처를 Mermaid `graph TD`/`graph LR` 로 작성 — 시각 표현력 부족, draw.io 사용 의무
- 시퀀스 흐름을 draw.io 로 작성 — 시간축 표현 불편, Mermaid 사용 의무
### Diagram 컨퍼런스급 표준 (필수 정독)
> [[rules/diagram-standards]] 에서 **컨퍼런스급(Toss SLASH / Kakao if(dev) / Naver DEVIEW 수준) 다이어그램 표준 v2 (minimalist-first)** 를 정의한다. 본 template 본문에 별도 기준을 두지 않는다 — 항상 `rules/diagram-standards.md` 를 정독.
>
> **핵심 원칙: "적을수록 좋다" (Less is more)**. 정보를 다이어그램에 몰아넣으면 청중이 어디부터 봐야 할지 모른다.
>
> v2 의 요약 (전체는 rules 정독):
>
> - **요소 수 상한** (HARD): Vertex ≤ 10 / Edge ≤ 8 / Callout ≤ 1 / Boundary group ≤ 3 / Legend 항목 ≤ 6 / 색상 ≤ 4
> - **박스 라벨 ≤ 2줄**, **화살표 라벨 ≤ 5단어**
> - **80% 회색/흑백 + 강조색 ≤ 2** (color salad 금지)
> - **Boundary 는 정보 있을 때만** (장식용 boundary 금지)
> - **Legend 는 표준 컨벤션이면 생략** (점선=외부 / cylinder=DB / 실선=동기 / 점선=비동기 는 legend 불필요)
> - **Callout 1개** (있을 때만) — 비자명한 함정·결정에만
> - **출처 wikilink 는 본문/캡션에**, 다이어그램 안에 박지 말 것
> - **스케일 어노테이션 (QPS/latency)** 은 다이어그램의 질문이 *성능* 일 때만
> - **5초 룰 + 30초 룰** 통과
>
> **8항 self-check checklist** ([[rules/diagram-standards]] §14) 를 모두 ✓ 해야 컨퍼런스 발표 가능 수준. 1개라도 미달 → 분할 또는 단순화.
>
> `wiki-diagram-reviewer` agent 가 위 기준으로 `.drawio` XML 을 grep-카운트 후 0~100 점수 부여, ≥95 PASS.
### 3.1 아키텍처 다이어그램 (draw.io XML)
> 컴포넌트 구성도. **저장 경로**: `raw/diagrams/<project-slug>/` 하위에 `.drawio` 또는 `.drawio.svg` 형식으로 저장. Obsidian draw.io 플러그인으로 더블클릭 편집.
>
> **파일 명명 규약**: `architecture-{viewpoint}-YYYY-MM-DD.drawio.svg`
> 예: `architecture-overview-2026-05-25.drawio.svg`, `architecture-deployment-2026-05-25.drawio.svg`, `architecture-data-flow-2026-05-25.drawio.svg`
>
> **임베드 작성 방법**: 아래 code block 형식을 참고해 실제 파일명을 채워 wikilink 작성. **placeholder 그대로 두지 말 것** — Obsidian이 placeholder를 파일명으로 채택해 root에 orphan 파일을 생성함.
```markdown
실제 사용 예 (drawio 파일 생성 후 placeholder 부분을 실제 값으로 치환):
![[raw/diagrams/my-project/architecture-overview-2026-05-25.drawio.svg]]
```
<!-- 본 템플릿 사용자: 위 code block 안의 line을 일반 wikilink로 옮기되, my-project 와 날짜를 실제 값으로 치환한 뒤에만 사용. -->
**다이어그램 작성 요약 (v2 minimalist, 상세는 [[rules/diagram-standards]] 정독):**
- **컴포넌트 라벨**: 시스템 이름 (Bold 1줄) + 핵심 한 줄 (Stack OR 역할, 둘 중 하나만). 절대 ≥3 줄 금지.
예: `**User Service**` / `Spring Boot 3.4 · :8080` (2줄)
- **화살표 라벨**: `<step?> <verb/protocol> <object>` — 5단어 이내
예: `① GET /`, `proxy_pass :8080`, `Kafka publish user.signed-up`
- **외부 시스템**: 점선 (`#D0D7DE`) + fill `#F6F8FA`. Legend 불필요 (표준 컨벤션)
- **Boundary**: Trust / Network / External — **정보 있을 때만**. 모든 컴포넌트를 boundary 1개 안에 넣지 말 것 (정보 0)
- **색상 ≤ 4** — 80% 회색 + 강조 ≤ 2 (blue / orange 한 family씩) + (선택) warning red callout
- **Legend 생략 가능** — 점선=외부 / cylinder=DB / 실선=동기 같은 표준 컨벤션이면 legend 불필요. 비표준 색·기호 있을 때만 ≤6 항목 legend.
- **데이터 모델 카디널리티** 는 ER 다이어그램 (Mermaid `erDiagram`)에서만. 아키텍처 다이어그램의 화살표에 `1..N` 같은 cardinality 박지 말 것.
<!-- section-id: architecture-components -->
### 3.2 컴포넌트 책임 분담
> 다이어그램의 각 컴포넌트가 정확히 무엇을 책임지는지 표로.
| 컴포넌트 | 역할 | 기술 스택 | 의존하는 외부 |
|---|---|---|---|
| `<name>` | <한 줄 책임> | <stack> | <외부 시스템> |
| `<name>` | <한 줄 책임> | <stack> | <외부 시스템> |
### 3.3 외부 의존성
| 외부 시스템 | 용도 | 통신 방식 | 장애 시 영향 (degrade / fail / fallback) |
|---|---|---|---|
| `<name>` | <용도> | <REST/gRPC/...> | <영향> |
### 3.4 배포 다이어그램
> 운영 환경 토폴로지가 비자명하면 별도 draw.io.
```markdown
실제 사용 예 (placeholder 치환 후 사용):
![[raw/diagrams/my-project/architecture-deployment-2026-05-25.drawio.svg]]
```
<!-- section-id: runtime-flow -->
## 4. 핵심 시퀀스
> **필수 섹션.** 최소 1개의 주요 user flow 를 Mermaid sequence diagram 으로. happy path + 주요 error path 함께.
<!-- section-id: sequence -->
### 4.1 <Flow name 1> (예: 사용자 로그인)
**시나리오**: <어떤 상황의 흐름인지 1줄>
```mermaid
sequenceDiagram
autonumber
actor User
participant FE as Frontend
participant API as Backend API
participant Auth as Auth Service
participant DB as DB
User->>FE: 로그인 폼 입력
FE->>API: POST /api/v1/login {email, password}
API->>Auth: validateCredentials()
Auth->>DB: SELECT user
DB-->>Auth: user row
alt 자격 증명 유효
Auth-->>API: AuthToken
API-->>FE: 200 OK {token}
FE-->>User: 메인 페이지 리다이렉트
else 자격 증명 무효
Auth-->>API: AuthenticationFailed
API-->>FE: 401 Unauthorized {error_code: AUTH_INVALID}
FE-->>User: 에러 표시
end
```
**시퀀스 작성 표준 (필수 준수):**
- **`autonumber` 활성화** — 본문에서 "단계 3에서 ..." 처럼 참조 가능
- **`actor` vs `participant`**: 사람은 `actor`, 시스템은 `participant`
- **순서**: User → Frontend → Backend → External (좌→우)
- **화살표 라벨 명세**:
- HTTP: `METHOD /path {body 요약}` (예: `POST /api/v1/login {email, password}`)
- 메시징: `event-name {payload 요약}` (예: `user.signed-up {userId}`)
- 메서드 호출: `method()` (예: `validateCredentials()`)
- **응답**: `-->>` (점선 화살표)
- **alt / opt / loop**: 분기·옵션·반복은 명시적 블록
- **`Note over X,Y`**: 비자명한 동작은 노트로 명시
- **에러 경로 1개 이상 필수**: happy path 만 그리면 미완성
### 4.2 <Flow name 2> (필요 시)
(반복)
## 5. 데이터 모델
> 핵심 엔터티가 5~10개 이상이면 ER 다이어그램으로. 그 미만이면 글로만.
```mermaid
erDiagram
USER ||--o{ ORDER : places
ORDER ||--|{ ORDER_ITEM : contains
PRODUCT ||--o{ ORDER_ITEM : "ordered as"
USER {
uuid id PK
string email
string name
}
ORDER {
uuid id PK
uuid user_id FK
timestamp created_at
decimal total
}
```
**ER 작성 표준:**
- **PK / FK 표시 필수**
- **관계 카디널리티 기호**:
- `||--||` (1:1)
- `||--o{` (1:N)
- `}o--o{` (M:N)
- `||..o{` (identifying vs non-identifying 표현)
- **관계 라벨**: 동사로 (예: `places`, `contains`, `ordered as`)
- 핵심 엔터티만 (5~10개 이내). 모든 테이블 그리지 말 것.
## 6. 기술 결정
> 주요 기술 선택과 이유. 트레이드오프 + 근거 자료 link 필수.
| 결정 영역 | 선택 | 검토한 대안 | 채택 이유 | 트레이드오프 | 근거 자료 |
|---|---|---|---|---|---|
| 백엔드 언어 | <e.g., Java 21> | <Kotlin / Go / Node> | <이유> | <단점> | `[[raw/official-docs/...]]` |
| 프레임워크 | <e.g., Spring Boot 3.4> | <Quarkus / Micronaut> | <이유> | <단점> | `[[raw/company-tech-blogs/...]]` |
| DB | <e.g., PostgreSQL 16> | <MySQL / MongoDB> | <이유> | <단점> | `[[raw/official-docs/...]]` |
| 메시징 | <e.g., Kafka / Redis Streams / X> | <대안> | <이유> | <단점> | |
| 캐시 | <e.g., Redis / Caffeine / X> | <대안> | <이유> | <단점> | |
| 아키텍처 패턴 | <e.g., Clean Architecture> | <Layered / Hexagonal / X> | <이유> | <단점> | |
| ... | | | | | |
<!-- section-id: project-decisions -->
## 6.1 안정 결정 레지스트리
> 프로젝트가 소유하는 결정의 SSOT. Decision ID 는 `DEC-<PROJECT>-<DOMAIN>-NNN`, revision 은 `1` 이상 정수다.
> `<PROJECT>` 와 `<DOMAIN>` 은 slug 를 uppercase kebab-case 로 정규화한다. 예: `DEC-CA-SKELETON-AUTH-001`.
> branch 는 결정 상세를 복제하지 않고 `DEC-CA-SKELETON-AUTH-001@2` 같은 **pinned reference + 1줄 요약**만 가진다.
> 결정 의미가 바뀌면 같은 ID 의 `Revision` 을 증가시키고 `project_revision` 도 증가시킨다. 단순 오탈자·링크 보정은 revision 증가 대상이 아니다.
| Decision ID | Revision | Domain | Decision Summary | Status | Owner | Evidence |
|---|---|---|---|---|---|---|
| `DEC-<PROJECT>-<DOMAIN>-001` | 1 | `<domain>` | <결정의 경계가 드러나는 1줄 요약> | `active` | `[[raw/project-notes/<project>]]` | `[[raw/official-docs/<...>]]` |
<!-- section-id: artifact-registry -->
## 6.2 Artifact Registry
| Artifact ID | Revision | Name | Schema Owner | Producer | Consumers | Schema Ref | Status |
|---|---:|---|---|---|---|---|---|
<!-- section-id: contract-gate-registry -->
## 6.3 Contract/Gate Registry
| Contract ID | Concern Key | Revision | Type | Owner | Trigger | Required Effect | Enforcement | Status |
|---|---|---:|---|---|---|---|---|---|
<!-- section-id: delegation-registry -->
## 6.4 Delegation Registry
| Delegation ID | Concern Key | Revision | Delegator | Delegate | Scope | Status |
|---|---|---:|---|---|---|---|
<!-- section-id: flow-stage-registry -->
## 6.5 Flow/Stage Registry
| Stage ID | Order | Owner | Input | Action | Output | Invariants | Revision |
|---|---:|---|---|---|---|---|---:|
<!-- section-id: implementation-boundaries -->
## 7. 비기능 요구사항
> 측정 가능한 비기능 목표. 없으면 명시적으로 "해당 없음".
- **성능**: <RPS, P99 latency 목표>
- **가용성**: <SLO 99.9% 등>
- **확장성**: <단일 인스턴스 / 다중 인스턴스 / HPA 정책>
- **보안**: <인증·인가 방식, 데이터 보호 정책, 컴플라이언스>
- **운영 / Observability**: <로깅·메트릭·트레이싱 정책>
- **재해 복구 / DR**: <RTO / RPO>
- **컴플라이언스**: <GDPR / PCI-DSS / 기타 / 해당 없음>
<!-- section-id: project-work-items -->
## 8.0 실행계획
> **`/project-spec` 가 채우는 핸드오프 SSOT.** Work Item ID 는 `WI-<PROJECT>-NNN` 이며 한 번 부여하면 재사용하지 않는다.
> 각 row 는 branch slug, 완료 조건, 적용할 project decision 의 pinned reference, 선행 Work Item, 상태를 묶는다.
> 결정 상세·메커니즘은 이 표나 branch 에 복제하지 않는다. project decision registry 를 owner 로 두고 pointer + 요약만 사용한다.
>
> 작성 규칙:
> - `Work Item ID` 의 `<PROJECT>` 는 project slug 의 uppercase kebab-case 형태다. 예: `WI-CA-SKELETON-001`.
> - `branch slug` 는 `rules/naming-conventions.md` §2.1 준수 (prefix 4종 `feature-`/`fix-`/`chore-`/`experiment-` 중 하나 + kebab-case, numbered hierarchy 금지).
> - `완료 조건` 은 **측정가능**해야 함 ("잘 된다" 금지). 그 branch 가 "끝났다"고 말할 수 있는 검증 가능한 결과.
> - `Applies Decisions` 는 쉼표로 구분한 `DEC-...@revision` 만 허용한다. unpinned ID 금지.
> - `Dependencies` 는 선행 `WI-...` ID 를 쉼표로 구분한다. 없으면 `-`.
> - `Status` 는 `planned` | `in-progress` | `blocked` | `done` | `cancelled` 중 하나다.
| Work Item ID | branch slug | 완료 조건 (측정가능) | Applies Decisions | Dependencies | Status |
|---|---|---|---|---|---|
| `WI-<PROJECT>-001` | `feature-<...>` | <이 branch 가 끝났다고 할 검증 가능한 결과> | `DEC-<PROJECT>-<DOMAIN>-001@1` | - | `planned` |
> 채운 뒤: `/branch-from-project <project> <WI-ID>` → `/branch-spec <slug> <근거 URL...>` → `/depth <slug>` 순으로 각 branch 를 깊게 작성.
## 8. 묶음 (이 프로젝트에 묶이는 모든 raw 자료)
> 본 project-note 는 cluster 의 entry point. 모든 branch / errors / interviews / lectures / job-postings / blog-topics / sources 가 여기로 upward link. hub 측에서도 카테고리별 명시.
### 8.1 브랜치 (project 의 직접 자식 branch — `parent_branch:` 비어있음)
> project-note 가 직접 가리키는 branch 들. 자식 branch 가 있는 branch 는 자기 Cluster 섹션에서 자식들을 참조하므로 여기에는 등재 안 함.
- `[[raw/branch-notes/<branch-1>]]` — <한 줄 요약>
- `[[raw/branch-notes/<branch-2>]]` — <한 줄 요약>
### 8.2 근거 자료 (프로젝트 전체 차원 foundational 조사)
> 특정 branch 에 묶이지 않는 전체 프로젝트 단위 근거 자료.
- `[[raw/official-docs/<...>]]`
- `[[raw/company-tech-blogs/<...>]]`
- `[[raw/lectures/<...>]]`
### 8.3 오류 기록 (branch 외 발생한 환경·운영 이슈)
- `[[raw/errors/<...>]]`
### 8.4 면접 준비 (프로젝트 전체 차원 면접 질문)
- `[[raw/interviews/<...>]]`
### 8.5 블로그·채용공고 연계 글감
- `[[raw/blog-topics/<...>]]` — 채용공고가 아닌 작업·학습·트러블슈팅 기반 글감 후보
- `[[raw/job-postings/<...>]]` — 채용공고에서 파생된 글감 후보
### 8.6 파생 wiki 문서
- canonical 검증 사실: `[[wiki/projects/<...>]]`
- 관련 일반 개념: `[[wiki/concepts/<...>]]`
- 포트폴리오: `[[wiki/portfolio/<...>]]`
- 블로그 글: `[[wiki/blog/<...>]]`
## 9. 검증 등급
> 본 project-note 의 각 부분이 어느 등급까지 검증되었는지. CLAUDE.md §15 lifecycle 참조.
| 영역 | 등급 | 근거 |
|---|---|---|
| 아키텍처 다이어그램 | `documented-only` \| `locally-verified` \| `prod-verified` | <근거 / 측정·로그·테스트> |
| 시퀀스 다이어그램 | 동일 | <근거> |
| 기술 결정 | 동일 | <근거> |
| 비기능 요구사항 | 동일 | <측정값 / SLO 모니터링 결과> |
### 9.1 실제 구현 내용 (`actually-implemented`)
> 코드에 존재하는 것만. 파일·함수 단위로 구체적으로. 면접에서 "구현했다"고 말해도 되는 부분.
### 9.2 로컬/dev 검증 (`locally-verified`)
> 로컬 또는 dev 환경에서 동작 확인한 부분. 어떻게 검증했는지(로그/테스트/측정값).
### 9.3 운영 검증 (`prod-verified`)
> 운영(prod) 환경에서 동작·성능을 확인한 부분. 근거(릴리즈 노트 / 운영 로그 / 모니터링 대시보드 / 인시던트 보고서)를 함께 명시.
### 9.4 문서/계획만 존재 (`documented-only`
> 설계 문서에만 있고 아직 구현 안 된 것. 면접에서 "구현했다"고 말하면 안 되는 부분.
## 10. 면접·외부 공개 답변 경계
### 10.1 자신 있게 답할 수 있는 범위
- <항목 1>
- <항목 2>
### 10.2 적당히 답할 수 있는 범위
- <항목>
### 10.3 답하면 안 되는 / "공식 문서 다시 확인" 해야 하는 범위
- <항목>
### 10.4 과장 금지 지점
> 외부에 설명할 때 사실보다 부풀려지기 쉬운 표현. 자기 검열용.
- <항목>
## 11. 아키텍처 검토 체크리스트 (작성·갱신 시 자체 점검)
> 본 project-note 가 hub 역할을 제대로 하려면 모두 ✓ 여야 함.
- [ ] 한 줄 요약 + 현재 상태 + 나의 역할 채워짐 (§1)
- [ ] 측정 가능한 성공 기준 1개 이상 (§2.3)
- [ ] **아키텍처 다이어그램 (`.drawio.svg`) 1개 이상 첨부** (§3.1)
- [ ] 다이어그램이 [[rules/diagram-standards]] v2 minimalist 통과 — `wiki-diagram-reviewer` 로 ≥95 점 (vertex ≤ 10 / edge ≤ 8 / callout ≤ 1 / 박스 라벨 ≤ 2줄 / 화살표 라벨 ≤ 5단어 / 80% 회색 + 강조 ≤ 2 / boundary 정보 있을 때만 / 5초 + 30초 룰)
- [ ] 외부 시스템이 점선 + 회색 fill 로 시각적 구분 (legend 불필요 — 표준 컨벤션)
- [ ] **시퀀스 다이어그램 1개 이상 (Mermaid)** — happy path + error path 함께 (§4)
- [ ] 데이터 모델은 5~10개 이상 엔터티 시에만 ER 그림 (§5)
- [ ] 주요 기술 결정 표에 트레이드오프 + 근거 자료 link 명시 (§6)
- [ ] 비기능 요구사항이 측정 가능한 수치 (§7)
- [ ] `project_revision` 이 양의 정수이고 Project Decision Registry 의 ID/revision 이 유효함 (§6.1)
- [ ] **Work Item Registry 채워짐** — 각 자식 branch 가 stable WI ID + naming-conventions slug + 측정가능 완료조건 + pinned decision refs 를 가짐 (§8.0)
- [ ] Cluster 섹션의 project 직접 자식 branch 목록 채워짐 (§8.1)
- [ ] 검증 등급이 각 영역별로 매겨짐 (§9)
- [ ] 면접 답변 경계 명시 (§10)
- [ ] 마지막 architecture review 날짜 frontmatter `architecture_review:` 에 기록
## 12. 다이어그램 파일 관리 가이드
> draw.io 파일과 Mermaid 코드 모두 본 project-note 와 함께 라이프사이클 관리.
### 12.1 draw.io (`.drawio.svg`)
- 저장 위치: `raw/diagrams/<project-slug>/`
- 명명: `architecture-{viewpoint}-{YYYY-MM-DD}.drawio.svg`
- viewpoint 예: `overview`, `deployment`, `data-flow`, `security`, `network`
- 갱신 시: 새 날짜로 파일 추가 + frontmatter `diagrams:` 에 모든 활성 다이어그램 나열
- 폐기 시: 파일 삭제하지 말고 `diagrams/<project>/archived/` 하위로 이동 + project-note 에서 link 제거
- Obsidian 임베딩 문법: `![[architecture-overview-2026-05-25.drawio.svg]]`
### 12.2 Mermaid
- 본 문서 본문에 직접. 외부 파일로 분리 안 함.
- 갱신 시: code block 그대로 수정 (git diff 친화적)
- 너무 커지면 (>50줄) 별도 sub-branch 의 branch-note 로 분리하고 본문에서는 요약만
### 12.3 그림 변경 시 의무
- 아키텍처가 변경되면 본 project-note 의 `architecture_review:` frontmatter 날짜 갱신
- 변경 사유는 §6 "기술 결정" 표에 한 줄 추가 (예: "2026-06-01: PostgreSQL → Aurora 변경 — 이유: 가용성 SLO 99.99%")
- 폐기된 결정도 표에서 지우지 말고 status 컬럼 추가로 표시 (`active` / `deprecated` / `superseded-by-<row>`)
## 13. 관련 개념
> §3~§6 표에 등장하지 않은 보조 개념·자료.
- `[[wiki/concepts/<...>]]`
- `[[wiki/projects/<...>]]`
- `[[raw/official-docs/<...>]]`
- `[[raw/company-tech-blogs/<...>]]`
## 14. 다음 단계
- [ ] <다음 마일스톤 / branch>
- [ ] <후속 학습 / 조사>
- [ ] <derived 산출물 후보>
@@ -0,0 +1,106 @@
---
title:
source_type: official-doc | company-tech-blog | personal-blog
url:
archive_url:
related_branches: []
related_projects: []
tags: []
created: YYYY-MM-DD
---
# {{title}}
> Layer: `raw/` — 외부 자료(공식 문서 / 대기업 기술 블로그)의 **원문 발췌·출처 기록**.
> 본 템플릿은 `raw/official-docs/` 와 `raw/company-tech-blogs/` 두 폴더가 공유.
> 검증된 요약은 `/ingest` 후 `wiki/concepts/`에 `source-summary-template` 형식으로 별도 작성. 원본은 raw에 영구 보관.
## source_type 허용값
frontmatter `source_type:` 에는 다음 중 하나만 사용:
- `official-doc` — 공식 레퍼런스 / 표준 / 사양 (예: Spring Boot reference, RFC, AWS docs)
- `company-tech-blog` — 대기업 엔지니어링 블로그 / 컨퍼런스 발표 글 (예: Stripe, Netflix, Toss, 카카오)
해당하지 않는 자료는 별도 카테고리 검토 (강의는 `raw/lectures/`, 채용공고는 `raw/job-postings/`, 일반 블로그 글감은 `raw/blog-topics/`).
## 활용 branch (필수, 최소 1개+)
> 이 자료는 **혼자 존재하지 않는다.** 어느 branch(또는 project)의 구현 결정의 **근거**로서 보관됨. 어느 작업의 어떤 결정을 정당화하는지 명시. 같은 자료가 여러 branch에서 인용될 수 있으면 frontmatter `related_branches` 에 모두 나열 + 아래 표에 추가.
| Branch | 이 자료가 정당화하는 결정 |
|---|---|
| `[[raw/branch-notes/{{branch-name-1}}]]` | <한 줄: 어떤 결정의 근거인지> |
| `[[raw/branch-notes/{{branch-name-2}}]]` | <한 줄> |
특정 branch 없이 foundational 조사로 수집한 경우:
- `[[raw/project-notes/{{project-name}}]]` — <어떤 프로젝트의 초기 조사인지>
## 출처
- 원본 URL:
- 아카이브 URL:
- 저자 / 조직:
- 발행일:
- 마지막 확인일: YYYY-MM-DD
## 왜 저장했는지
> 이 자료를 보관하는 이유 1~2줄. 어떤 개념·문제·결정과 연결되는가. Parent 표의 "정당화하는 결정"과 일관되어야 함.
<이유>
## 핵심 인용
> 원문 그대로. 따옴표·줄바꿈 보존. 페이지·섹션 번호 있으면 같이.
> [§<section>] "원문 발췌 1."
> [§<section>] "원문 발췌 2."
> [§<section>] "원문 발췌 3."
## 추출된 주장
> 이 자료가 **직접 말하는 것만** claim 으로 분리한다. 내 프로젝트에 적용한 결론은 여기 쓰지 않는다.
> `Claim ID` 는 같은 raw 문서 안에서 안정적으로 유지한다. 예: `C1`, `C2`, `C3`.
| Claim ID | Claim (이 자료가 직접 말하는 것) | Evidence quote | Strength | Applies to | Does not prove |
|---|---|---|---|---|---|
| C1 | <원문이 직접 지지하는 주장> | [§<section>] "<짧은 원문 인용>" | `official-strong` | <적용 가능한 조건> | <이 claim 으로 증명할 수 없는 것> |
| C2 | <주장> | [§<section>] "<짧은 원문 인용>" | `case-study` | <조건> | <한계> |
### Strength 허용값
- `official-standard` — RFC, 표준 사양, 언어/프로토콜 표준
- `official-vendor-doc` — Spring, Keycloak, AWS, Google 등 공식 벤더 문서
- `official-reference` — 공식 reference/API 문서
- `company-case-study` — 대기업/실무 기술 블로그의 특정 사례
- `engineering-blog` — 개인/팀 블로그의 엔지니어링 해설
- `tutorial` — 튜토리얼/가이드. 일반화 금지
- `needs-confirmation` — 원문만으로는 적용 판단 불가
## 적용 경계
- 이 자료가 직접 증명하는 것:
- `C1`: <직접 증명 범위>
- 이 자료가 증명하지 않는 것:
- <예: 특정 설정이 모든 런타임에서 기본 활성화된다는 뜻은 아님>
- 내 프로젝트에 적용하려면 추가 확인이 필요한 것:
- <예: ca-tmpl 의 실제 Spring Security 설정에서 동작 검증 필요>
## 메모
> 나중에 wiki로 옮길 때 참고할 짧은 메모. 검증되지 않은 내 추론은 여기에 두지 말 것 (그것은 wiki/concepts의 source-summary 또는 wiki/projects 본문에서만 작성).
- 인용 1 해석 후보 (미검증):
- 추가로 봐야 할 동일 출처 페이지:
## 관련
> 같은 주제의 다른 raw 자료, 또는 이 자료를 인용한 wiki 문서.
- 같은 주제 다른 official-doc / company-tech-blog: `[[raw/<...>]]`
- 이 자료를 인용한 wiki 요약: `[[wiki/concepts/<...>]]` (생성 시)
@@ -0,0 +1,64 @@
---
title:
source_type: source-summary
status: draft
confidence: unknown
tags: []
related_projects: []
last_reviewed:
url:
archive_url:
---
# {{title}}
> Layer: `wiki/concepts/` — 외부 자료의 **검증된 요약 문서**. 원문 발췌와 출처 기록 자체는 `raw-source-template`을 사용해 `raw/`에 보관하고, 본 문서는 그 raw를 참조해 작성합니다.
## 출처
- 원본 URL:
- 아카이브:
- 저자/조직:
- 발행일:
## 핵심 인용 (35문장)
> 원문 발췌 1.
> 원문 발췌 2.
## 요약
자료의 핵심 주장 24줄.
## 내 해석
원문이 말한 것과 내가 추론한 것을 **분리**해서 작성.
- **원문이 말한 것**:
- **내 해석/추론**:
## Claim Map
> raw source 의 `Claims Extracted` 를 wiki 요약으로 승격할 때, 원문 claim 과 내 해석을 분리해 보존한다.
| Claim ID | Source claim | Wiki interpretation | Confidence | Linked decisions |
|---|---|---|---|---|
| `raw/<category>/<slug>.md#C1` | <원문 claim 요약> | <내 해석> | `high` | `raw/branch-notes/<branch>.md#D1` |
| `raw/<category>/<slug>.md#C2` | <원문 claim 요약> | <내 해석> | `medium` | <없으면 N/A> |
## 적용 경계
- 이 자료를 근거로 말할 수 있는 것:
- 이 자료만으로 말하면 안 되는 것:
- 내 프로젝트에서 추가 검증이 필요한 것:
## 평가
- 이 자료가 공식 기준인가, 사례인가? (`source_type` 따라 다름)
- 어떤 한계가 있는가?
## 관련 개념
- `[[{{related-concept}}]]`
@@ -0,0 +1,51 @@
---
title:
source_type: project
status: draft
confidence: unknown
tags: []
related_projects: []
last_reviewed:
---
# {{title}}
> Layer: `wiki/projects/` — canonical 실무 적용 문서(내 프로젝트 사실). 일반 개념은 `wiki/concepts/`, raw 프로젝트 hub는 `raw/project-notes/`(`project-template.md`) 사용.
> 본 문서는 **하나의 토픽/결정 영역** 슬라이스다. 프로젝트 전체 hub(아키텍처·시퀀스·Cluster)는 `wiki/projects/<project>.md` named-hub(MOC)와 그 SSOT인 `raw/project-notes/` 가 담당한다.
> 증거 등급(`actually-implemented`/`locally-verified`/`prod-verified`/`documented-only`/`planned`)을 섹션별로 분리해 외부 공개 가능 범위를 명확히 한다 (CLAUDE.md §6/§15).
## 프로젝트 컨텍스트
> 이 슬라이스가 다루는 결정/토픽의 배경. 문제 배경 + 검토한 선택지 + 결정 이유를 여기에 접어 서술(별도 필수 섹션 아님). 외부인이 "무엇을 왜 이렇게 했는가"를 1분에 이해할 수 있어야 함.
## 실제 구현 내용 (`actually-implemented`)
> 코드에 실제 존재하는 것만. 파일·클래스·task 단위로 구체적으로. 면접에서 "구현했다"고 말해도 되는 부분. 가능하면 ground-truth(레포 경로/커밋) 대조 근거를 함께.
## 로컬/dev 검증 (`locally-verified`)
> 로컬 또는 dev 환경에서 동작 확인한 부분. 어떻게 검증했는지(테스트 명령/로그/측정값)를 명시.
## 운영 검증 (`prod-verified`)
> 운영(prod) 환경에서 검증된 부분. 릴리즈 노트/운영 로그/모니터링/인시던트 근거. 없으면 "없음"이라고 명시.
## 문서/계획만 존재 (`documented-only`
> 설계/문서에만 있고 아직 구현 안 된 것. 면접·외부 공개에서 "구현했다"고 말하면 안 되는 부분. 후속 branch로 위임되는 항목은 링크.
## 면접에서 말할 수 있는 범위
> 자신 있게 / 적당히 / 답하면 안 되는 범위로 구분. 증거 등급과 일치해야 함.
## 과장 금지 지점
> 외부 설명 시 사실보다 부풀려지기 쉬운 표현. 자기 검열용.
## 관련 개념
> `[[wiki/concepts/...]]` 양방향 링크. 일반 개념과 본 프로젝트 사실을 연결.
## 근거 자료
> 근거. 추출 출처 branch-note/raw, 그리고 ground-truth 레포. `[[raw/branch-notes/...]]`, `[[raw/project-notes/...]]` 등.