308 lines
14 KiB
Markdown
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`을 기록한다. 해시는 직접 만들지 않는다.
|
|
- 내보내기는 승인 해시를 다시 비교하고 원본을 덮어쓰지 않은 채 근거 주석만 제거한 별도 파일을 만든다. 다른 작업 메모는 자동 제거하지 않고 검증 단계에서 차단한다.
|