Files
cover-letter-haness/skills/draft-korean-it-cover-letter/references/data-model.md
T

308 lines
14 KiB
Markdown

# 작업 데이터 모델
## 목차
1. 저장 원칙
2. 파일 구조
3. 프로필
4. 경험과 근거
5. 지원처와 문항
6. 세션
7. ID와 상태 규칙
8. 무결성 규칙
## 1. 저장 원칙
`.cover-letter/`는 개인 작업 데이터 디렉터리다. 기본적으로 Git에서 제외하고 공유하지 않는다.
다음 계층을 섞지 않는다.
1. 사용자가 실제로 제공한 원문과 자료
2. 그 원문에서 추출한 사실 후보
3. 사용자가 확인한 사실
4. 모델이 제안한 가치·인과 해석
5. 승인 개요와 파생 초안
초안은 원천 사실을 변경할 수 없다. 사실이나 공개 권한이 바뀌면 해당 근거를 참조하는 개요와 초안을 재검증한다.
## 2. 파일 구조
```text
.cover-letter/
├── .gitignore
├── profile.json
├── stories.json
├── applications.json
├── session.json
├── drafts/
└── exports/
```
템플릿은 스킬의 `assets/`에 있고 `harness.py init`이 복사한다. 초기화는 기존 JSON을 덮어쓰지 않지만, 개인 작업공간의 0700/0600 권한과 내부 `.gitignore``*` 규칙은 안전한 값으로 복구한다.
대화에 들어온 이력서·회고의 원문은 기본적으로 다시 저장하지 않는다. `.cover-letter/`에는 사용자가 확인할 수 있는 최소 요약만 둔다. `session.pending_confirmations`는 확정 전 모델 해석을 잠시 보관하는 배열이며 원천 사실, 작성 컨텍스트, 승인 해시에 포함되지 않는다. 경험의 선택 필드 `uncertainties``conflicts`는 문자열 배열이다. 둘 중 하나라도 비어 있지 않으면 해당 경험은 `confirmed/locked`일 수 없고 `captured/conflicted`로 되돌려야 한다. 이 하네스는 자동 수정 이력을 만들지 않으므로 사실을 고친 뒤에는 영향을 받는 문항을 다시 검증한다. 비밀·토큰·제3자 민감정보 원문은 어떤 이력에도 보존하지 않는다.
## 3. 프로필
`profile.json`의 기본 구조다.
```json
{
"schema_version": 1,
"candidate": {
"career_level": "신입",
"target_roles": ["백엔드 개발"],
"current_status": "졸업 예정",
"motivation": {
"why_it": "관찰한 문제를 재현하고 푸는 과정이 좋았음",
"why_role": "서버 동작을 끝까지 추적하는 일에 흥미가 있음",
"future_direction": "신뢰할 수 있는 서비스를 개발",
"evidence_ids": ["E001", "V001"]
}
},
"values": [
{
"id": "V001",
"statement": "추측 전에 관찰한다",
"origin": "캡스톤 회고",
"behavior": "재현 조건과 로그를 먼저 확인한다",
"story_ids": ["E001"],
"status": "confirmed",
"use_permission": "allowed"
}
],
"voice": {
"samples": [],
"preferred_tone": [],
"avoid_phrases": []
},
"privacy": {
"do_not_use": [],
"redactions": []
},
"confirmed": true
}
```
`values.status``captured`, `confirmed`, `locked` 중 하나이고, 모든 가치에는 `use_permission: ask|allowed|blocked`를 명시한다. `confirmed/locked` 가치에는 비어 있지 않은 `statement`, `origin`, `behavior`, 하나 이상의 실제 `story_ids`가 필요하다. 한 경험만 뒷받침하는 가치관은 지속적인 성향이 아니라 해당 경험 이후 생긴 기준으로 표현한다.
`profile.confirmed=true`로 올리려면 `career_level`, 하나 이상의 `target_roles`, `current_status`, 확인된 `motivation.why_it`, `motivation.why_role`, 하나 이상의 `motivation.evidence_ids`가 필요하다. `motivation.evidence_ids`에는 `confirmed/locked`이면서 사용이 허용된 `E/V`만 둔다. 지원동기·입사 후 방향 문장은 이 ID로 추적하고, 동기만으로 새 사건을 만들지 않는다. 문항의 승인 개요에 들어 있지 않은 동기와 동기 근거는 해당 작성 컨텍스트에 포함하지 않는다.
문체 표본에는 가능하면 다음을 둔다.
```json
{
"id": "W001",
"kind": "project-retrospective",
"text": "사용자가 직접 쓴 원문",
"user_authored": true,
"use_permission": "allowed"
}
```
개인정보 필드의 의미는 다음과 같다.
- `do_not_use`: 로컬에 남겨도 되는 짧은 금지 문자열만 둔다. CLI가 초안과 컨텍스트에서 정확 일치를 차단한다. 자격증명, 주민번호, 고객 원문처럼 저장 자체가 위험한 값은 여기에 넣지 말고 즉시 삭제한다.
- `redactions`: “고객사는 업종으로 일반화” 같은 사람·에이전트용 익명화 메모다. CLI가 자동 치환하지 않으므로 초안 검증 전에 직접 적용한다.
## 4. 경험과 근거
`stories.json`은 경험 카드 배열을 가진다.
```json
{
"schema_version": 1,
"stories": [
{
"id": "E001",
"title": "외부 API 재시도 문제 추적",
"period": "2025-03",
"context": "캡스톤 프로젝트 데모 준비",
"constraints": ["데모 전날", "외부 API 변경 불가"],
"user_role": "로그 추가와 재시도 설정 변경",
"team_role": "백엔드 기능 구현과 데모 준비",
"decisions": ["DB 수정 전에 구간별 로그로 병목을 확인"],
"actions": ["요청 구간별 시간을 기록", "재시도 조건 확인"],
"alternatives": ["DB 인덱스 변경은 근거가 없어 보류"],
"outcomes": {
"measured": [],
"observed": ["데모 시나리오에서 멈춤이 재현되지 않음"],
"attribution": "설정 변경은 직접 수행했고 전체 데모 성공은 팀 결과",
"owner_scope": "shared"
},
"reflection": "이후 추측으로 수정하기 전에 재현 조건을 기록함",
"skills": ["logging", "API timeout", "debugging"],
"value_ids": ["V001"],
"evidence": [
{
"id": "F001",
"claim": "정확한 개선률은 측정하지 않음",
"source": "사용자 확인",
"verified": true,
"use_permission": "allowed",
"owner_scope": "shared"
}
],
"status": "confirmed",
"use_permission": "allowed"
}
]
}
```
경험 상태:
- `captured`: 사용자 원문에서 잡았지만 아직 요약을 확인하지 않음
- `confirmed`: 역할, 행동, 결과 범위를 사용자가 확인함
- `conflicted`: 자료나 답변 사이에 모순이 있음
- `locked`: 사용자가 확정했고 명시적 수정 전에는 바꾸지 않음
사용 권한:
- `ask`: 최종 사용 전에 다시 확인
- `allowed`: 해당 범위로 자기소개서 사용 허용
- `blocked`: 초안과 컨텍스트에서 제외
결과 소유 범위:
- `user`: 해당 결과를 사용자 개인 결과로 표현해도 되는 범위
- `team`: 팀·프로젝트 결과이며 반드시 팀 결과와 본인 행동을 분리
- `shared`: 사용자 기여가 있지만 결과 전체를 개인 성과로 단정할 수 없음
사용 허용된 `confirmed/locked` 경험에는 최소한 `title`, `user_role`, 하나 이상의 `actions`, 측정 또는 관찰 결과, `outcomes.attribution`, `outcomes.owner_scope`가 필요하다. 세부 `F###`에도 결과 소유가 중요한 경우 `owner_scope`를 적는다. 상위 `E###`만 연결했다고 해서 모든 `F###` 수치가 자동으로 허용되지는 않는다.
`context`는 위에 정의된 필드만 허용 목록으로 복사한다. `outcomes`, 공고, 요구사항, 개요, 세부 근거에 임의 중첩 키를 추가해도 모델 컨텍스트로 전달하지 않는다. 서명·토큰 쿼리가 있는 URL과 스킴 없는 사설 호스트·IP 엔드포인트도 제거한다.
근거 유형은 문서·산출물과 사용자 기억을 모두 허용한다. 개인 경험에 반드시 외부 증빙을 요구하지 않는다. 다만 숫자, 자격, 기간, 성능, 운영 규모는 측정 조건이나 자료를 더 엄격히 확인한다.
## 5. 지원처와 문항
`applications.json` 구조다.
```json
{
"schema_version": 1,
"applications": [
{
"id": "A001",
"company": "예시테크",
"role": "백엔드 개발",
"posting": {
"text": "공고 원문",
"source": "회사 채용 페이지",
"captured_at": "2026-07-17"
},
"requirements": [
{
"id": "R001",
"text": "장애 원인을 논리적으로 분석",
"priority": "high",
"story_ids": ["E001"]
}
],
"confirmed": true,
"questions": [
{
"id": "Q001",
"prompt": "문제 해결 경험을 작성해 주세요.",
"character_limit": 700,
"character_minimum": null,
"count_spaces": true,
"required_format": "plain_text",
"story_ids": ["E001"],
"outline": {
"thesis": "추측보다 재현 가능한 근거를 먼저 만든다.",
"beats": ["첫 가설", "로그 확인", "설정 변경", "관찰 결과", "후속 습관"],
"evidence_ids": ["E001", "F001", "V001"]
},
"outline_approved": true,
"draft_file": ".cover-letter/drafts/A001-Q001-v1.md",
"status": "outline_approved",
"verification": {
"facts_checked": false,
"ownership_checked": false,
"privacy_checked": false,
"question_fit_checked": false,
"voice_confirmed": false,
"interview_explainable": false,
"draft_sha256": null,
"context_sha256": null
}
}
]
}
]
}
```
회사와 공고 정보에는 출처와 확인 시점을 둔다. 사용자에게 유리해 보이는 회사 문화나 사업 방향을 모델이 임의로 추가하지 않는다.
확정 지원처에는 `company`, `role`, 공고 원문 또는 하나 이상의 요구사항, `posting.source`, `posting.captured_at`이 필요하다. 출처 없는 요구사항을 `A/R` 근거로 올리지 않는다. 승인 개요에는 적어도 하나의 `E###` 경험이 필요하며, 지원동기 문항도 사용자의 선택·행동 근거를 하나 이상 연결한다.
`required_format`은 현재 `plain_text`, `markdown`, `null`만 지원한다. 소제목 수, 바이트 제한, 문단 수처럼 포털 고유 규칙은 별도 확인 항목으로 관리한다. 글자 수는 정규화된 제출 텍스트의 Python 문자 수이며, 공백 포함 시 내부 개행도 센다. 실제 포털의 바이트·개행·이모지 계산과 다를 수 있으므로 마지막 붙여넣기 화면에서 다시 확인한다.
문항 상태는 `captured`, `mapped`, `outline_proposed`, `outline_approved`, `drafted`, `verified`, `user_approved`, `needs_recheck`를 사용한다.
`prompt`는 상태와 관계없이 문자열이어야 한다. `outline_approved=true`이면 상태도 `outline_approved`, `drafted`, `verified`, `user_approved`, `needs_recheck` 중 하나여야 한다. 객체형 프롬프트나 승인 상태와 충돌하는 진행 포인터는 컨텍스트 생성 전에 차단한다.
## 6. 세션
`session.json`은 진행 편의를 위한 포인터이며 원천 사실이 아니다.
```json
{
"schema_version": 1,
"stage": "NEW",
"active_application_id": null,
"active_question_id": null,
"pending_confirmations": [],
"updated_at": null
}
```
허용 단계는 `NEW`, `SCOPED`, `COLLECTING`, `PERSONAL_MODEL_CONFIRMED`, `TARGET_READY`, `QUESTION_READY`, `OUTLINE_APPROVED`, `DRAFTED`, `VERIFIED`, `USER_APPROVED`, `NEEDS_RECHECK`다. `status`가 보여 주는 단계는 저장된 포인터를 그대로 신뢰하지 않고 현재 확인 상태와 승인 해시를 다시 계산한 결과다.
## 7. ID와 상태 규칙
| 접두어 | 대상 |
|---|---|
| `E` | 경험 카드 |
| `F` | 세부 사실·근거 |
| `V` | 가치관 |
| `W` | 문체 표본 |
| `A` | 지원처 |
| `R` | 공고 요구사항 |
| `Q` | 자기소개서 문항 |
ID는 삭제 후 재사용하지 않는다. 초안 내부 근거 주석에는 개인 경험·사실·가치관을 위한 `E/F/V`와 확인된 공고·요구사항을 위한 `A/R`을 사용한다. `W``Q`는 작성 자료와 문항 식별자이므로 근거 주석에는 쓰지 않는다.
```markdown
<!-- evidence: E001,V001 -->
본문 문단
<!-- evidence: A001,R001 -->
확인된 공고 사실을 사용하는 문단
```
주석 하나는 바로 뒤 문단의 핵심 사실을 모두 뒷받침해야 한다. 한 주석으로 문서 전체를 포괄하지 않는다.
## 8. 무결성 규칙
- 모든 ID는 종류별로 유일해야 한다.
- `story_ids`, `value_ids`는 실제 존재하는 ID만 참조해야 한다.
- `confirmed` 또는 `locked` 경험만 최종 초안에 사용할 수 있다.
- 경험은 `use_permission: allowed`여야 컨텍스트에 포함할 수 있고, 경험 안의 세부 근거도 확인·허용된 항목만 남긴다.
- 지원처와 문항은 초안 전에 확인되어야 한다.
- `outline_approved`가 아니면 최종형 초안을 만들지 않는다.
- 초안의 근거 주석에 없는 ID나 사용 금지 ID가 있으면 차단한다.
- 문항에 연결된 초안은 모든 본문 문단에 근거 주석이 필요하고, 승인 개요의 `evidence_ids` 밖 근거는 차단한다.
- 한 문장에 둘 이상의 경험 계열 `E###`/그 하위 `F###`을 합치지 않는다.
- 초안의 숫자는 값과 단위가 연결된 정확한 근거에 존재하는지 검사하고, 의미와 측정 조건은 사람이 다시 확인한다.
- 팀·공동 결과는 `owner_scope`와 본인 행동을 분리한다.
- 연결 근거의 행동 단어 하나만 겹친다고 새 결과를 허용하지 않는다. 결과 문장은 결과 필드의 구체 명사와 연결되어야 하고, 숫자와 `백만 명` 같은 한글 수량도 근거에 있어야 한다.
- `uncertainties` 또는 `conflicts`가 남은 경험은 확정하거나 내보낼 수 없다.
- `[확인 필요]`, `TODO`, 보이지 않는 문자, 비정규화 한글은 확정할 수 없다.
- 원천 사실이나 공개 권한이 바뀌면 참조 문항을 `needs_recheck`로 바꾼다.
- `approve --confirm-all`이 여섯 사용자 확인과 `draft_sha256`, `context_sha256`을 기록한다. 해시는 직접 만들지 않는다.
- 내보내기는 승인 해시를 다시 비교하고 원본을 덮어쓰지 않은 채 근거 주석만 제거한 별도 파일을 만든다. 다른 작업 메모는 자동 제거하지 않고 검증 단계에서 차단한다.