careermate 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (137) hide show
  1. package/AGENTS.md +33 -0
  2. package/INSTALL.md +230 -0
  3. package/LICENSE +21 -0
  4. package/README.md +532 -0
  5. package/THIRD_PARTY_NOTICES.md +57 -0
  6. package/bin/careermate.mjs +77 -0
  7. package/dist/career-os/README.md +78 -0
  8. package/dist/career-os/eop/cover-letter.md +46 -0
  9. package/dist/career-os/eop/fit-analysis.md +48 -0
  10. package/dist/career-os/eop/interview-prep.md +39 -0
  11. package/dist/career-os/eop/job-analysis.md +42 -0
  12. package/dist/career-os/eop/profile-extraction.md +37 -0
  13. package/dist/career-os/knowledge/ats.md +131 -0
  14. package/dist/career-os/knowledge/company-research.md +137 -0
  15. package/dist/career-os/knowledge/cover-letter.md +135 -0
  16. package/dist/career-os/knowledge/fit-matching.md +121 -0
  17. package/dist/career-os/knowledge/human-writing.md +118 -0
  18. package/dist/career-os/knowledge/interview-behavioral.md +132 -0
  19. package/dist/career-os/knowledge/interview-technical.md +126 -0
  20. package/dist/career-os/knowledge/linkedin-profile.md +152 -0
  21. package/dist/career-os/knowledge/networking-referrals.md +166 -0
  22. package/dist/career-os/knowledge/offer-evaluation-decision.md +121 -0
  23. package/dist/career-os/knowledge/onboarding-first-90-days.md +126 -0
  24. package/dist/career-os/knowledge/portfolio.md +121 -0
  25. package/dist/career-os/knowledge/recruiter-screen.md +105 -0
  26. package/dist/career-os/knowledge/rejection-triage-iteration.md +115 -0
  27. package/dist/career-os/knowledge/resume.md +123 -0
  28. package/dist/career-os/knowledge/salary-negotiation.md +123 -0
  29. package/dist/career-os/knowledge/verifiers/ats-compat.md +64 -0
  30. package/dist/career-os/knowledge/verifiers/consistency.md +61 -0
  31. package/dist/career-os/knowledge/verifiers/human-voice.md +82 -0
  32. package/dist/career-os/knowledge/verifiers/recency-staleness.md +72 -0
  33. package/dist/career-os/knowledge/verifiers/responsiveness-on-target.md +82 -0
  34. package/dist/career-os/knowledge/verifiers/truthfulness.md +67 -0
  35. package/dist/doctor.mjs +79094 -0
  36. package/dist/mcp.mjs +96108 -0
  37. package/dist/migrate.mjs +4735 -0
  38. package/dist/pdf.worker.min.mjs +28 -0
  39. package/dist/public/app.js +150 -0
  40. package/dist/public/fonts/PretendardVariable.woff2 +0 -0
  41. package/dist/public/icon-180.png +0 -0
  42. package/dist/public/index.html +52 -0
  43. package/dist/public/lib.js +394 -0
  44. package/dist/public/pages/applications.js +107 -0
  45. package/dist/public/pages/documents.js +467 -0
  46. package/dist/public/pages/home.js +261 -0
  47. package/dist/public/pages/interview.js +227 -0
  48. package/dist/public/pages/jobs.js +493 -0
  49. package/dist/public/pages/profile.js +556 -0
  50. package/dist/public/pages/settings.js +240 -0
  51. package/dist/public/styles.css +498 -0
  52. package/dist/site/analytics.js +97 -0
  53. package/dist/site/favicon.svg +1 -0
  54. package/dist/site/fonts/PretendardVariable.woff2 +0 -0
  55. package/dist/site/icon-180.png +0 -0
  56. package/dist/site/icon-512.png +0 -0
  57. package/dist/site/index.html +598 -0
  58. package/dist/site/landing.js +54 -0
  59. package/dist/site/llms-install.txt +217 -0
  60. package/dist/site/robots.txt +4 -0
  61. package/dist/site/sitemap.xml +21 -0
  62. package/dist/site/start.html +326 -0
  63. package/dist/site/style.css +550 -0
  64. package/dist/site/vercel.json +20 -0
  65. package/dist/web.mjs +46852 -0
  66. package/docs/FAQ.md +101 -0
  67. package/docs/MCP_TOOLS.md +311 -0
  68. package/docs/README.md +28 -0
  69. package/docs/START_WORKFLOW.md +137 -0
  70. package/docs/SUPPORTED_AI_APPS.md +112 -0
  71. package/docs/WORKFLOWS.md +202 -0
  72. package/docs/career-os/README.md +78 -0
  73. package/docs/career-os/eop/cover-letter.md +46 -0
  74. package/docs/career-os/eop/fit-analysis.md +48 -0
  75. package/docs/career-os/eop/interview-prep.md +39 -0
  76. package/docs/career-os/eop/job-analysis.md +42 -0
  77. package/docs/career-os/eop/profile-extraction.md +37 -0
  78. package/docs/career-os/knowledge/ats.md +131 -0
  79. package/docs/career-os/knowledge/company-research.md +137 -0
  80. package/docs/career-os/knowledge/cover-letter.md +135 -0
  81. package/docs/career-os/knowledge/fit-matching.md +121 -0
  82. package/docs/career-os/knowledge/human-writing.md +118 -0
  83. package/docs/career-os/knowledge/interview-behavioral.md +132 -0
  84. package/docs/career-os/knowledge/interview-technical.md +126 -0
  85. package/docs/career-os/knowledge/linkedin-profile.md +152 -0
  86. package/docs/career-os/knowledge/networking-referrals.md +166 -0
  87. package/docs/career-os/knowledge/offer-evaluation-decision.md +121 -0
  88. package/docs/career-os/knowledge/onboarding-first-90-days.md +126 -0
  89. package/docs/career-os/knowledge/portfolio.md +121 -0
  90. package/docs/career-os/knowledge/recruiter-screen.md +105 -0
  91. package/docs/career-os/knowledge/rejection-triage-iteration.md +115 -0
  92. package/docs/career-os/knowledge/resume.md +123 -0
  93. package/docs/career-os/knowledge/salary-negotiation.md +123 -0
  94. package/docs/career-os/knowledge/verifiers/ats-compat.md +64 -0
  95. package/docs/career-os/knowledge/verifiers/consistency.md +61 -0
  96. package/docs/career-os/knowledge/verifiers/human-voice.md +82 -0
  97. package/docs/career-os/knowledge/verifiers/recency-staleness.md +72 -0
  98. package/docs/career-os/knowledge/verifiers/responsiveness-on-target.md +82 -0
  99. package/docs/career-os/knowledge/verifiers/truthfulness.md +67 -0
  100. package/package.json +89 -0
  101. package/packages/core/src/context.ts +74 -0
  102. package/packages/core/src/index.ts +8 -0
  103. package/packages/core/src/onboarding.ts +81 -0
  104. package/packages/core/src/services.ts +187 -0
  105. package/packages/core/src/summary.ts +104 -0
  106. package/packages/db/src/connection.ts +76 -0
  107. package/packages/db/src/index.ts +23 -0
  108. package/packages/db/src/paths.ts +52 -0
  109. package/packages/db/src/repositories.ts +891 -0
  110. package/packages/db/src/runtime.ts +58 -0
  111. package/packages/db/src/schema.ts +307 -0
  112. package/packages/exporters/src/html.ts +110 -0
  113. package/packages/exporters/src/index.ts +364 -0
  114. package/packages/exporters/src/markdown.ts +178 -0
  115. package/packages/knowledge/src/index.ts +168 -0
  116. package/packages/mcp-tools/src/bridge.ts +106 -0
  117. package/packages/mcp-tools/src/index.ts +17 -0
  118. package/packages/mcp-tools/src/result.ts +49 -0
  119. package/packages/mcp-tools/src/tools.ts +747 -0
  120. package/packages/mcp-tools/src/update.ts +330 -0
  121. package/packages/parsers/src/documents.ts +533 -0
  122. package/packages/parsers/src/html.ts +86 -0
  123. package/packages/parsers/src/index.ts +231 -0
  124. package/packages/parsers/src/keywords.ts +151 -0
  125. package/packages/prompts/src/humanize.ts +59 -0
  126. package/packages/prompts/src/index.ts +82 -0
  127. package/packages/prompts/src/install.ts +43 -0
  128. package/packages/prompts/src/onboarding.ts +35 -0
  129. package/packages/prompts/src/system.ts +57 -0
  130. package/packages/shared/src/build-info.ts +22 -0
  131. package/packages/shared/src/enums.ts +142 -0
  132. package/packages/shared/src/index.ts +19 -0
  133. package/packages/shared/src/schemas.ts +453 -0
  134. package/packages/workflows/src/definitions.ts +109 -0
  135. package/packages/workflows/src/index.ts +39 -0
  136. package/scripts/init.ts +371 -0
  137. package/tsconfig.json +32 -0
@@ -0,0 +1,137 @@
1
+ # 회사 리서치 / Company Research — CareerMate 지식 (Phase A)
2
+
3
+ > 이 문서는 CareerMate가 **연결된 AI에게 제공(serve)** 하는 지식이다. CareerMate 안에는 LLM이 없다 — 분석·작성·검증은 연결된 AI가 수행하고, 이 플레이북·루브릭은 그 AI가 **세계 최고 수준**으로 일하도록 안내한다.
4
+
5
+ ## 1. 무엇을 하는가
6
+
7
+ CareerMate 사용자를 대신해 지원 대상 회사·산업·보상을 리서치하고, 그 리서치를 **맞춤 면접 답변·고가치 질문·적합도 판정(go/no-go)** 으로 변환한다. 사고(synthesis)는 연결된 AI(Claude/GPT/Gemini)가 하고, CareerMate는 공고·프로필·적합도 분석·면접 자료를 MCP로 저장·제공한다. 핵심 규율은 다섯 가지다 — (1) 7개 캐논 앵커(미션/전략, 제품, 최근뉴스, 문화·인재상, 직무·레벨, **경쟁사·시장 포지션**, 보상)를 덮는다, (2) 출처 우선순위(1차/공식 > 2차/언론 > 3차/리뷰)를 지키고 교차검증·날짜를 붙인다, (3) 모든 사실을 STAR 훅·질문·적합도 플래그 중 하나로 **변환**한다(원시 사실은 미완성), (4) 모든 주장을 **이름·날짜가 붙은 출처**에 귀속시킨다, (5) **출처를 실제로 가져올 수 없으면 지어내지 말고 미검증으로 선언**한다.
8
+
9
+ **중요(정직한 한계):** 아래 루브릭은 LLM 없이 셀 수 있는 **완성도·형식 게이트**다. 출처가 **진짜인지·주장을 실제로 뒷받침하는지·정말 변환됐는지** 같은 품질·진위는 패턴/카운트로 검증할 수 없다 — 그 최종 품질 판단은 연결된 AI 본인의 책임이다. 루브릭은 "얇거나 출처 없는 리서치"를 사전에 걸러낼 뿐, 진실성을 보증하지 않는다.
10
+
11
+ ## 2. 플레이북
12
+
13
+ ### 원칙
14
+
15
+ - **7개 캐논 앵커를 덮어라: 미션/전략, 제품/비즈니스모델, 최근뉴스(≤6개월), 문화·인재상, 직무·레벨, 경쟁사·시장 포지션, 보상(협상 단계에 한함).** — 대학 커리어센터는 회사+산업+직무의 다축 커버리지로 수렴하며, 단일 축("About 페이지만 읽음")은 면접관이 즉시 할인한다. 경쟁사 축은 "왜 X가 아니라 우리냐"라는 최강 적합도 신호를 만든다. _(출처: UF Career Connections Center "Four Steps"; Ohio State ECS; Letscareer DART 경쟁사 비교)_
16
+ - **출처를 등급화하라: 회사 1차 자료(공식 사이트·블로그·채용공고·공시 DART 사업보고서)=Tier-1, 평판 있는 2차/언론=Tier-2, 자기선택 리뷰 플랫폼=Tier-3 신호.** — 리뷰 사이트 별점은 작고 비무작위인 자기선택 표본으로, 극단(매우 만족/매우 불만) 응답자에 치우친다. Tier-3 단독 근거로 결론을 내리지 마라. _(출처: BGSU ScholarWorks "Construct Validity of Glassdoor Ratings"; PubMed "Incentives can reduce bias")_
17
+ - **단, 잡플래닛의 면접 후기(질문 유형·전형 절차)는 별점과 구분해 취급하라.** — 한국 맥락에서 잡플래닛 **면접 후기**는 회사별 실제 질문·분위기를 담은, 별점보다 훨씬 actionable한 거의-1차에 가까운 제보다. 별점은 Tier-3로 두되, 면접 후기는 "회사별 제보(교차검증 권장)"로 가중치를 높여라. _(출처: 잡플래닛 면접후기)_
18
+ - **모든 비자명 주장은 ≥2개 독립 출처로 교차검증하라. 출처가 하나면 '미검증'으로 라벨링하라('단일 Glassdoor 리뷰에 따르면…').** — 어떤 단일 크라우드소스 데이터 1건은 사실이 아니라 가설이다. _(출처: UF "Four Steps" 링크드인 동문 교차확인; Ohio State ECS)_
19
+ - **최근성 타임스탬프: 모든 '최근 뉴스' 항목에 날짜를 붙이고 ~6개월 이내를 선호하라. 6개월 초과는 '최근'으로 부르지 말고, 12~18개월 초과는 스테일로 표시하라.** — 구체적·최근 동향 언급은 면접에서 가장 강한 신뢰 신호이며, 낡은 '최근'은 정반대로 준비 부족을 드러낸다. _(출처: UF "Four Steps"; Ohio State ECS)_
20
+ - **출처를 실제로 가져올 수 없으면(웹/도구 접근 없음, 학습 컷오프 이후) 날짜를 지어내지 말고 해당 앵커를 '미검증/라이브 출처 없음'으로 선언하라.** — 이것이 최대 날조 리스크다. YYYY-MM 정규식은 날짜가 **실재하는지** 검증하지 못한다 — 가짜 날짜로 게이트를 통과시키지 마라. _(출처: 본 플레이북 안티-날조 원칙; AGENTS.md 추측 금지)_
21
+ - **각 리서치 사실을 세 산출물 중 하나로 변환하라: (a) 사용자 강점↔회사 니즈를 잇는 STAR/답변 훅, (b) 면접관 질문, (c) 적합도 플래그(pro/con).** — 리서치의 목적은 답변 맞춤·적합도 판정·고가치 질문이다. 변환되지 않은 사실은 길이만 늘리는 미완성 출력이다. _(출처: Hays "How to research an employer"; Randstad RiseSmart STAR)_
22
+ - **면접관 질문 3~5개를 '공개 웹사이트만으로는 답할 수 없는' 특정 사실 기반 개방형(how/what)으로 만들고, 각 질문이 어느 앵커 사실에서 파생됐는지 기록하라(based_on_anchor).** — 홈페이지 너머를 읽었음을 증명하는 질문이 진정성·시니어리티를 신호한다. _(출처: Ohio State ECS; Indeed "27 Smart Questions"; UndercoverRecruiter)_
23
+ - **가능하면 면접관·팀 레이어까지 리서치하라: 패널의 역할/재직기간/최근 글, 직무가 속한 팀의 미션·제품영역·최근 팀 블로그.** — '웹사이트로 답 안 되는' 질문은 회사 전체가 아니라 **그 팀**에서 나온다. (라이브 출처 없으면 미검증으로 표시.) _(출처: UF "Four Steps" 링크드인 현직자; Ohio State ECS)_
24
+ - **적합도는 판정으로 끝내라: pro/con 플래그를 모두 만들고, 명시적 go/no-go 한 줄과 함께 ≥1개의 con(또는 disqualifier 검토)을 반드시 포함하라.** — con 없는 all-pro는 사용자가 듣고 싶은 말만 하는 확증편향이다. _(출처: 본 플레이북 적합도 판정 원칙)_
25
+ - **공고에 앵커링하라: 공고 상위 키워드/요건을 추출하고, '공고 키워드 → 사용자 강점 → 회사 니즈'를 잇는 매핑 레코드(triple)를 만들어라.** — 키워드를 단순 반복(echo)하는 게 아니라 강점·니즈와 묶는 것이 변환이다. _(출처: Letscareer DART 분석; Hays 강점-공고 정렬)_
26
+ - **보상은 협상 단계에 한해 다루고, 시장에 맞게 분해하라.** 글로벌 빅테크는 levels.fyi로 레벨 매핑 후 base/bonus/equity 분해. **한국·비테크·SME·공공은 equity가 거의 없고 포괄임금·상여(13th·성과급)·직급(사원/대리/과장)이 1급 구조다 — equity를 강요하지 마라.** DART 직원 평균 급여는 **전사 평균**이지 직급/직무 밴드가 아니다 — 밴드 앵커로 쓰지 마라. _(출처: levels.fyi 협상 가이드; MIT CAPD; DART 사업보고서 주의)_
27
+
28
+ ### Do
29
+
30
+ - 연결 직후 `get_application_context`로 대상 공고·프로필·강조 포인트를 먼저 확보하고 그 위에 외부 리서치를 얹어라.
31
+ - 7개 앵커를 체크리스트로 돌며 각 항목에 최소 1개의 출처(이름+날짜)를 붙여라. 못 채운 앵커는 침묵하지 말고 '미확인/해당없음(사유)'으로 명시하라.
32
+ - 리뷰 사이트 항목은 '제보 기반 신호'로 라벨링하고, 같은 결론을 받치는 2차 출처를 1개 더 찾아 교차검증하라. (잡플래닛 면접후기는 별점보다 가중치를 높이되 여전히 교차확인.)
33
+ - 최근 6개월 내 뉴스(출시·투자·조직개편·리더십)를 ≥1개 찾아 면접 오프닝/질문에 구체적으로 인용하라. **라이브로 못 찾으면 '미검증'으로 표시**하라.
34
+ - 경쟁사 ≥2곳과 그 대비 '우리의 차별점' 1줄을 확보해 "왜 X가 아니라 여기냐"에 답할 수 있게 하라.
35
+ - 모든 사실을 STAR 훅·질문·적합도 플래그 중 하나로 변환하고, 변환 안 된 원시 사실은 `gaps`로 보류하라.
36
+ - 면접관 질문 3~5개를 특정 사실 기반 개방형으로 만들고 각 질문에 `based_on_anchor`를 기록하라.
37
+ - 적합도 판정에 명시적 go/no-go 한 줄과 ≥1개의 con을 포함하라.
38
+ - 공고 키워드를 '키워드→강점→니즈' triple로 매핑해 저장하라(단순 반복 금지).
39
+ - 보상은 **협상 단계에서만** 다루고, 한국이면 직급·상여·포괄임금 구조로, 글로벌 테크면 base/bonus/equity+levels.fyi로 분해하라.
40
+ - 공개 자료가 희박한 회사(SME·스텔스 스타트업)는 솔직히 '공개 발자국 희소'로 보고하고, 빈 앵커를 면접 질문으로 전환하는 계획을 제시하라.
41
+ - 최종 산출은 `save_fit_analysis`·`save_interview_prep`로 저장하고 대시보드 링크(`http://127.0.0.1:4319`)를 안내하라.
42
+
43
+ ### Don't
44
+
45
+ - 리뷰 단일 별점·험담을 검증 없이 사실로 단정하지 마라(작고 비무작위인 자기선택 표본).
46
+ - '좋은 문화', '성장하는 회사' 같은 출처 없는 일반론으로 리서치를 채우지 마라.
47
+ - 회사 About 페이지만 읽고 리서치를 끝냈다고 하지 마라(단일 축·단일 출처 결론 금지).
48
+ - 라이브 출처를 못 가져오는데 날짜·뉴스를 **지어내지** 마라 — 미검증으로 선언하라.
49
+ - 12~18개월 지난 뉴스를 '최근'이라 부르지 마라. 6개월 초과면 '최근' 라벨을 떼라.
50
+ - 공개 웹사이트만으로 답 나오는 질문('주력 제품이 뭔가요?', '앞으로 어떻게 성장하나요?')을 면접 질문으로 내지 마라.
51
+ - 보상을 단일 숫자로 인용하지 마라. **DART 전사 평균을 직급 밴드처럼 쓰지 마라.** equity 없는 한국 직무에 equity를 억지로 끼워 fail-flag 하지 마라.
52
+ - 면접 전 단계에서 보상 협상을 무리하게 끌어올리지 마라(보상은 오퍼/협상 단계 게이팅).
53
+ - 공고·강점과 연결하지 않은 채 회사 사실만 나열하지 마라(에코 ≠ 변환).
54
+ - all-pro 플래그만 내고 '판정'이라 부르지 마라(확증편향).
55
+ - 사용자 데이터를 외부로 보내거나, 미검증 추정을 사실로 단정해 지어내지 마라(불확실하면 사용자에게 확인).
56
+
57
+ ### 워크드 예시 (Before → After)
58
+
59
+ 1. **Before:** "이 회사는 좋은 기업 문화로 유명하고 성장하고 있어서 지원했습니다. 제품도 훌륭하고 비전이 멋집니다."
60
+ **After:** "공식 블로그(2026-03)에 따르면 귀사는 동남아 결제 인프라로 확장 중이고, 업계 보도 2곳에서 교차확인된 시리즈C(2026-02)를 마쳤습니다. 경쟁사 A·B 대비 차별점은 다국가 정산 정합성 자동화로 보입니다. 저는 핀테크 정산 시스템을 다국가로 확장한 경험(처리량 3배↑)이 있어, 공고의 '글로벌 결제 트래픽 처리' 요건(키워드)→제 강점→귀사의 확장 니즈로 직접 연결됩니다. — 면접 질문(based_on: 최근뉴스): '동남아 확장에서 reconciliation을 어느 단계까지 자동화하셨고, 다음 분기 병목은 어디라고 보시나요?'"
61
+ **왜 더 나은가:** 출처+날짜, 교차검증된 최근뉴스, 경쟁사 차별점, 그리고 키워드→강점→니즈 triple과 앵커 기반 개방형 질문으로 변환됐다. Before는 출처 없는 일반론이라 어느 회사에나 붙는다.
62
+
63
+ 2. **Before:** "Glassdoor 별점이 2.9이고 '워라밸이 나쁘다'는 리뷰가 있어 이 회사는 워라밸이 안 좋습니다."
64
+ **After:** "Glassdoor·잡플래닛(제보 기반 신호, 자기선택 표본이라 편향 가능) 일부 리뷰에 '성수기 야근' 언급이 있습니다 — 단정하지 않습니다. 교차확인: 채용공고에 '온콜 로테이션' 문구, 링크드인 현직자 1명이 '분기 마감 주간만 집중'이라 확인 → 결론은 '상시 야근'이 아니라 '특정 주기 피크'. 적합도 con 플래그로 기록하고, 면접에서 '온콜/마감 주기의 빈도와 보상 방식'을 직접 물어 확인할 것."
65
+ **왜 더 나은가:** Tier-3를 신호로만 라벨링하고 2차 출처로 교차검증해 과장된 결론을 보정했으며, 미확인 항목을 con 플래그+면접 질문으로 전환했다. Before는 단일 출처를 사실로 단정한 안티패턴이다.
66
+
67
+ 3. **Before:** "이 직무 연봉은 약 6천만 원 정도로 알고 있습니다."
68
+ **After:** "(협상 단계에서) **한국 법인**이라면: 잡플래닛 연봉 제보(N건, 직급=대리 기준)와 DART 사업보고서의 **전사** 평균 급여를 *참고치로만* 교차확인하고, 포괄임금 여부·상여/성과급 구조·직급(사원/대리/과장)을 분해해 묻습니다 — DART 평균은 직급 밴드가 아니므로 밴드로 쓰지 않습니다. **글로벌 테크**라면: levels.fyi에서 해당 회사 레벨(공고의 'Senior'에 *근사* 매핑, 회사별로 다를 수 있음)의 base/bonus/equity 중앙값(데이터 N건, 갱신 2026-Q2)으로 분해합니다. 어느 쪽이든 단일 숫자가 아니라 밴드+구조로 협상 앵커를 잡습니다."
69
+ **왜 더 나은가:** 시장별로 구조를 분리(한국=직급·상여·포괄임금, 글로벌=base/bonus/equity)하고, DART 평균을 밴드로 오용하지 않으며, 레벨 매핑이 근사임을 명시했다. 보상을 협상 단계로 게이팅했다. Before는 출처·구조·레벨이 없는 단일 숫자라 협상에 쓸 수 없다.
70
+
71
+ ## 3. 검증 루브릭 (연결된 AI가 산출물을 이 기준으로 자가검증)
72
+
73
+ > **설계 원칙:** 루브릭은 **연결된 AI가 EMIT하는 구조화 필드**(아래 §5 data shape의 `anchors[]`, `questions[]`, `fit_flags[]`, `mappings[]` 등) 위에서 **존재여부·non-null·개수**를 센다 — 산문에 정규식을 돌리지 않는다. 이는 측정을 게임하기 어렵게 만들고 LLM 없이 결정적으로 통과/실패를 낸다. 단, 이 게이트들은 **완성도·형식**만 본다 — 진위·출처 유효성·진짜 변환 여부는 검증하지 못한다(연결된 AI 책임).
74
+
75
+ | ID | 검사 항목 | 합격 기준 | 측정 방법(LLM 없이 셀 수 있게) |
76
+ |----|-----------|-----------|--------------------------------|
77
+ | R1 | 7개 캐논 앵커 커버리지 | `anchors[].key`가 7종 중 ≥6종 존재 AND 각 앵커의 `facts[]`가 비어있지 않거나 `status`가 `unverified`/`n/a(사유)`로 명시 | `anchors` 배열에서 distinct `key` 수와, 빈 `facts[]`의 `status` non-null 여부를 카운트 |
78
+ | R2 | 사실당 출처 귀속 | `anchors[].facts[]`의 각 fact가 `source_name` non-null AND `source_tier∈{1,2,3}` 보유 비율 ≥90% | fact 객체에서 `source_name!=null && source_tier!=null` 개수 ÷ 전체 fact 수 (구조 필드 카운트) |
79
+ | R3 | 최근뉴스 날짜 + 스테일 FAIL | `recent_news` 앵커에 `dated`(YYYY-MM) 있는 fact ≥1 AND **'최근'으로 라벨된 fact의 `dated`가 6개월 이내**; 6개월 초과를 '최근'으로 표기하면 FAIL | `dated` 필드 파싱 후 기준일과의 개월차 계산; `label=='recent' && months_diff>6`이면 실패 카운트>0 |
80
+ | R4 | 라이브 출처 없음 정직 선언 | 라이브 검색 불가 시 해당 fact는 `retrieved=false` AND `status='unverified'`; `retrieved=false`인데 `dated`만 채워진 fact 0건 | `retrieved==false && dated!=null && status!='unverified'` 위반 건수=0 |
81
+ | R5 | Tier-3 단독 결론 없음 | `source_tier==3`만으로 도출된 결론 fact는 `cross_verified==true`(독립 2차 출처 `source_name` 동반) 또는 `signal_only==true` 라벨 | tier3 fact 중 `cross_verified==false && signal_only==false` 건수=0 (구조 플래그 카운트) |
82
+ | R6 | 질문 사양 + 앵커 출처 | `questions[]` 개수 3~5 AND 각 question이 `based_on_anchor` non-null AND `open_ended==true` (AI가 EMIT한 플래그) | `questions` 길이 ∈[3,5]; `based_on_anchor!=null && open_ended==true` 비율=100% |
83
+ | R7 | 공고 매핑 triple | `mappings[]`에 `{keyword, user_strength, company_need}` 3필드 모두 non-null인 완전 triple ≥3개 | triple 객체에서 세 필드 동시 non-null 개수 카운트 ≥3 (에코가 아니라 매핑) |
84
+ | R8 | 적합도 판정(con 강제) | `fit_flags[]`에 `type=='con'` ≥1 AND `verdict` 필드(go/no-go) non-null | `fit_flags` 중 `type=='con'` 개수≥1 그리고 `verdict!=null` |
85
+ | R9 | 보상 시장별 분해(조건부) | `comp`가 존재하고 `phase=='negotiation'`일 때만 평가: `market=='kr'`이면 `{직급, 상여/성과급, 포괄임금여부}` 중 ≥2 + DART는 `band==false`; `market=='global'`이면 `{base, bonus, equity?}` 중 ≥2 + `level_map_approximate==true` | `comp.phase`로 게이팅; 시장별 요구 필드 non-null 개수 카운트, equity는 kr에서 optional |
86
+
87
+ **주요 실패 모드:**
88
+ - **형식 통과 = 품질 통과로 착각.** R1~R9는 모두 표면 형식(필드 존재·개수)만 본다. 가짜 출처명·boilerplate `cross_verified=true`·진짜 매핑이 아닌 triple은 잡지 못한다 — 진위·변환 품질은 연결된 AI가 책임진다.
89
+ - **날짜 날조.** 라이브 출처 없이 그럴듯한 YYYY-MM을 채워 R3을 통과시키는 것. R4가 `retrieved` 플래그로 1차 방어하지만, AI가 정직하게 EMIT해야만 작동한다.
90
+ - **에코 ≠ 변환.** 공고 명사를 답변에 복붙해 키워드만 늘리는 것(구 bag-of-words 함정). R7은 완전 triple만 세서 단순 반복을 거른다.
91
+ - **확증편향(all-pro).** con 없는 판정. R8이 `type=='con'` ≥1을 강제한다.
92
+ - **US-테크 편향.** equity·levels.fyi·L\d 레벨을 한국·비테크 직무에 강요해 정상 리서치를 fail-flag. R9가 시장별로 분기하고 equity를 kr에서 optional로 둔다.
93
+ - **얇은 데이터 회사를 날조로 메움.** SME·스텔스의 빈 앵커를 지어내 채우는 것. R1이 `status='unverified'`/`n/a(사유)`를 허용해 정직한 공백을 합격으로 인정한다.
94
+
95
+ ## 4. 출처 (Provenance)
96
+
97
+ - **UF Career Connections Center — Four Steps for Researching an Employer** — 캐논 앵커(미션/문화/제품/뉴스), 다출처 교차검증, 링크드인 현직자 확인, 최근 게시물 언급 전략 · https://career.ufl.edu/four-steps-for-researching-an-employer/
98
+ - **Ohio State Engineering Career Services — How to Research a Company for an Interview** — 여러 소스 결합(Handshake/Glassdoor/LinkedIn/Google), 리서치 기반 3~5개 질문 준비 · https://www.ecs.osu.edu/news/2025/02/how-research-company-interview
99
+ - **BGSU ScholarWorks — Examining the Construct Validity of Glassdoor.com Ratings** — 리뷰 사이트 자기선택·비무작위 표본 편향을 Tier-3 신호로만 다루는 근거(정성적 방향성; 단일 보편 상수로 인용 금지) · https://scholarworks.bgsu.edu/cgi/viewcontent.cgi?article=1099&context=pad
100
+ - **PubMed — Incentives can reduce bias in online employer reviews** — 자원/자기선택 리뷰가 더 극단적이라는 실증 → 단일 리뷰 단정 금지 · https://pubmed.ncbi.nlm.nih.gov/33764122/
101
+ - **levels.fyi — Ultimate Negotiation Guide & leveling methodology** — (글로벌 테크 한정) 레벨 *근사* 매핑, total comp의 base+bonus+equity 분해, 협상 앵커링. 한국·비테크·SME 커버리지는 희소함에 유의 · https://www.levels.fyi/blog/ultimate-negotiation-guide.html
102
+ - **MIT CAPD — How to negotiate your tech salary ft. levels.fyi** — 보상 데이터를 레벨에 매핑해 협상 앵커로 쓰는 교육 자료 · https://capd.mit.edu/resources/how-to-negotiate-your-tech-salary-ft-levels-fyi-video/
103
+ - **Hays — How to research an employer before an interview** — 리서치를 STAR 답변·맞춤 질문으로 변환, 강점을 공고/회사 목표에 정렬 · https://www.hays.co.uk/career-advice/article/interview-prep-employer-research
104
+ - **Indeed — 27 Smart Questions to Ask in an Interview** — 리서치 기반 개방형 질문 설계 기준 · https://www.indeed.com/career-advice/interviewing/smart-questions-to-ask-in-an-interview
105
+ - **Letscareer — DART 사업보고서 분석 방법** — 한국 맥락: '사업의 내용'·'경영진 의견' 분석을 지원 동기/면접 차별화로 연결, **경쟁사 비교**. 단 직원 평균 급여는 전사 평균이지 직급 밴드가 아님에 유의 · https://www.letscareer.co.kr/blog/65/
106
+ - **잡플래닛 (JobPlanet)** — 한국 맥락 소스. 별점=Tier-3 신호이나 **면접 후기(질문 유형·전형)는 거의-1차에 가까운 actionable 제보**로 가중치 상향(교차검증 전제) · https://www.jobplanet.co.kr/
107
+
108
+ ## 5. Phase B 힌트 (아키텍처로 연결)
109
+
110
+ - **MCP 도구 아이디어:**
111
+ - `get_company_research_brief(job_id)` — 대상 공고에 묶인 7개 캐논 앵커 슬롯(미션/전략, 제품, 최근뉴스, 문화·인재상, 직무·레벨, **경쟁사·시장**, 보상) 작업판을 반환. 각 앵커에 '사실+출처명+날짜+신뢰등급(Tier1/2/3)+retrieved/cross_verified 플래그' 배열, 공고 상위 키워드, 사용자 강점 목록, 빈/미검증/스테일 앵커를 표시하는 `gaps`.
112
+ - `save_company_research(job_id, anchors[], mappings[], questions[], fit_flags[], comp?)` — 결과를 구조화 필드로 저장.
113
+ - `validate_company_research(payload)` — §3 R1~R9를 **LLM 없이 구조 필드 카운트/존재여부**로 돌려 `{check_id, passed, measured_value}` 배열 반환. 정규식-온-프로즈가 아니라 EMIT된 struct 위에서만 측정.
114
+ - **데이터 형태 힌트:**
115
+ ```
116
+ {
117
+ job_id,
118
+ posting_keywords: string[],
119
+ user_strengths: string[],
120
+ anchors: { key: 'mission'|'product'|'recent_news'|'culture'|'level'|'competitor'|'comp',
121
+ status: 'filled'|'unverified'|'n/a',
122
+ facts: [{ text, source_name, source_tier: 1|2|3, dated: 'YYYY-MM'|null,
123
+ retrieved: boolean, cross_verified: boolean, signal_only: boolean,
124
+ label?: 'recent' }] }[],
125
+ mappings: [{ keyword, user_strength, company_need }], // 완전 triple만 카운트
126
+ comp?: { phase: 'research'|'negotiation', market: 'kr'|'global',
127
+ // kr: { 직급?, 상여?, 성과급?, 포괄임금여부?, dart_band: false }
128
+ // global: { base?, bonus?, equity?, level_map_approximate: true } },
129
+ generated: {
130
+ questions: [{ text, based_on_anchor, open_ended: boolean }], // 3~5개
131
+ fit_flags: [{ type: 'pro'|'con', text, source_name }], // con ≥1
132
+ verdict: 'go'|'no-go'|'conditional' // non-null 강제
133
+ },
134
+ gaps: string[],
135
+ validation: [{ check_id, passed: boolean, measured_value }]
136
+ }
137
+ ```
@@ -0,0 +1,135 @@
1
+ # 자기소개서 / Cover Letter — CareerMate 지식 (Phase A)
2
+
3
+ > 이 문서는 CareerMate가 **연결된 AI에게 제공(serve)** 하는 지식이다. CareerMate 안에는 LLM이 없다 — 분석·작성·검증은 연결된 AI가 수행하고, 이 플레이북·루브릭은 그 AI가 **세계 최고 수준**으로 일하도록 안내한다.
4
+
5
+ ## 1. 무엇을 하는가
6
+
7
+ 자기소개서/커버레터는 이력서를 산문으로 다시 쓴 글이 아니라, **특정 회사·직무를 겨냥한 설득 문서**다. 검증된 뼈대는 hook → fit(왜 나, 증거) → why-this-company → close이며, 각 주장은 형용사가 아니라 행동+정량 결과(STAR-lite) 한 단락으로 증명한다. 가장 흔한 실패는 **회사명을 바꿔도 말이 되는 제너릭 편지**(빈 형용사, 회사 고유 근거 없음, 이력서 불릿 복붙)다. CareerMate는 LLM이 없으므로, 검증 루브릭을 **두 종류로 정직하게 분리**한다 — (A) 순수 정규식·카운트로 저장 전 자동 검사 가능한 항목, (B) 연결 AI의 의미 판단이 필요한 항목. 또한 한국 자소서(문항형·글자수·인재상)와 영문 커버레터(단일 레터·ATS)는 **로케일별로 다른 루브릭**을 적용한다.
8
+
9
+ ## 2. 플레이북
10
+
11
+ ### 원칙
12
+
13
+ - **구조를 hook → fit(증거) → why-this-company → close 4역할로 고정하되, locale='ko' 문항형 자소서는 문항당 별도 글로 다룬다.** 영문 단일 레터는 4역할이 각각 한 문단 이상 존재해야 한다. 한국 자소서는 보통 3~5개 문항('지원동기/성장과정/직무역량/입사후포부')이 각각 별개 글이고 글자수 제한도 다르므로, 4역할 단일 레터를 강제하지 말고 **문항별 두괄식(결론→증명→직무·인재상 연결)** 로 매핑한다. _(출처: Georgetown Cawley Career Center; Princeton Cover Letter Guide; 한국 대기업 공채 자소서 문항 관행)_
14
+ - **형용사로 자신을 묘사하지 말고, 그 형용사가 참임을 증명하는 구체적 사례로 대체하라.** '소통을 잘한다' 대신 '야간 피킹 라인을 3개월 주도해 오배송률 4.1%→1.2%'처럼 행동+전후 델타를 쓴다. 빈 형용사뿐 아니라 '~라고 생각합니다', '많은 것을 배웠습니다', '~을 통해 성장했습니다', '~에 기여하고 싶습니다' 같은 **증거 없는 자기서술 종결구문**도 슬롭이다. _(출처: LiveCareer/CareerAddict Cover Letter Mistakes; Linkareer 두괄식 작성법)_
15
+ - **각 핵심 주장은 STAR-lite로 증명하되, 한 통/한 문항에 1~2개의 대표 경험만 깊게 다뤄라.** 결과(R)는 **'규모'가 아니라 '본인 행동으로 인한 변화량'** 이다. '100억 규모 프로젝트 담당'은 임팩트가 아니다 — '전환율 60→210(+250%)'이 임팩트다. S/T 압축은 글자수 빠듯한 문항의 기본값이되, 경험 서술형 문항은 평가자가 맥락을 요구하므로 **문항 유형에 따라 S/T 분량을 조절**한다. _(출처: Harvard FAS Mignone Center; 매거진한경 KKK-STAR)_
16
+ - **이력서를 줄단위로 반복하지 마라.** 커버레터는 이력서가 못 담는 '왜·어떻게·맥락'을 더한다. 다만 한국어는 교착어라 표면형이 달라도 의미가 같을 수 있으니, 중복 판정은 단순 n-gram이 아니라 의미 기준으로 본다. _(출처: 4 Corner Resources; LiveCareer)_
17
+ - **'왜 이 회사인가'를 회사 고유 근거(미션·제품·최근 활동·인재상/핵심가치)로 1~3문장 명시하라.** 회사명을 placeholder로 바꿔도 말이 되는 문장은 실패다. _(출처: University of Maryland Cover Letter Resources; Catch 합격 자소서)_
18
+ - **본문의 모든 수치·고유명사는 저장된 사용자 데이터(get_resumes·경력·프로젝트)에 출처가 있어야 한다.** 정량화를 강조하되 **없는 수치를 발명하도록 압박하지 마라** — 면접에서 즉시 무너진다. 근거가 없으면 약한 주장을 빼되 숫자를 지어내지 않는다. _(출처: CareerMate AGENTS.md 사실 보존 원칙; get_writing_style_guide)_
19
+ - **공고 핵심 요구사항을 본인 증거와 1:1 매핑하되 키워드 스터핑을 피하라.** 단, `get_application_context`의 `job.requirements`/`job.keywords`는 **선택적 자유텍스트 배열**이라 '상위 N개 랭킹'이 보장되지 않는다. 비어 있으면 이 매핑 체크는 **skip(N/A)** 처리한다. _(출처: Yale HR/Career Development; Scale.jobs Keyword Mistakes)_
20
+ - **분량/글자수는 로케일별로 다르다.** 영문 학생 커버레터는 3/4~1페이지(≈250~400단어). 한국 자소서는 문항당 500~1000자가 흔하고 **상한뿐 아니라 하한**(예: 최소 500자)도 평가에 들어가며, 글자수 기준이 **공백 포함/제외/byte** 로 공고마다 갈린다(가장 흔한 실격 사유). _(출처: University of Cincinnati Guide; 한국 자소서 글자수 관행)_
21
+ - **수신자 실명·직무명 지정은 로케일 의존이다.** 영문/외국계 다이렉트 지원은 'To whom it may concern' 대신 채용담당자 실명을 쓴다. 한국 공채/플랫폼은 시스템 폼 입력이라 수신자 특정이 불가능하므로 실명 지정을 강제하지 않는다. _(출처: Harvard via CNBC; 한국 공채 지원 폼 현실)_
22
+ - **블라인드 채용 가드레일을 지켜라.** 한국 NCS/공정채용 기조상 나이·성별·사진·가족관계·출신지 등 직무무관 개인정보는 자소서에 넣지 않는다. _(출처: NCS 블라인드 채용 가이드 기조)_
23
+ - **직무 유형·지원자 경로별로 기준을 차등하라.** 경력직(임팩트·리더십·P&L), 신입/인턴(잠재력·학습속도·전이가능 스킬), 기술직(설계 디테일) vs 영업/마케팅(정량 KPI)은 평가축이 다르다. 신입·경력단절·직무전환자는 정량 실적이 빈약하므로 **'숫자 ≥2'를 강요하지 말고** 프로젝트·학습 사례로 fit을 증명하게 한다. _(출처: Harvard 직무 직결 경험 권고; 채용 실무 차등)_
24
+
25
+ ### Do
26
+
27
+ - 영문 도입 첫 문장에 (직무명 + 가장 관련 있는 경험 한 가지 + 회사에 대한 구체적 한 줄)을 넣어라. 한국 문항은 결론(직무 강점/지원동기)을 첫 문장에 두는 두괄식으로 시작하라.
28
+ - 각 강점 주장 뒤에 STAR-lite 한 단락(행동 → **전후 델타형 정량 결과**)을 붙여 증명하라.
29
+ - '왜 이 회사'를 회사 고유 사실(제품·미션·최근 뉴스·인재상)로 못박아라.
30
+ - 성과를 **전/후 비교(X→Y), 증감률(+N%), 금액·기간**으로 정량화하되, 그 수치가 저장된 이력서·경력 데이터에 근거가 있는지 확인하라.
31
+ - 약점·실패·갈등 문항은 정량 성과가 아니라 **성찰·개선 행동**으로 답하라(이 문항에 'quantified ≥2'를 강요하지 마라).
32
+ - 글자수 제한을 적용할 때 **count_mode(공백포함/공백제외/byte)** 를 먼저 확인하라.
33
+ - 클로징에 명확한 다음 단계(면접 요청/연락 가능 시점)를 한 문장으로 넣어라(로케일상 가능할 때).
34
+ - 저장 전 lint(루브릭 자동 검사)를 통과시킨 뒤 save_cover_letter_version으로 보관하라.
35
+ - 초안은 get_writing_style_guide의 문체를 적용해 사람이 쓴 듯 자연스럽게 다듬어라.
36
+
37
+ ### Don't
38
+
39
+ - 'I am writing to apply for…' / 'I have always been passionate about' / 'As a recent graduate' / '저는 ~에 지원합니다' / '어릴 적부터', '~을 보며 자랐습니다', '저는 ~한 사람입니다', '평소 ~에 관심이 많아' 같은 상투적·성장기 도입으로 시작하지 마라.
40
+ - '성실한·책임감·열정·소통을 잘하는 / 꼼꼼한·끈기있는·헌신적인·주도적인 / hard-working·team player·detail-oriented·motivated·proactive·dedicated·diligent·people person' 같은 **증거 없는 평가형 형용사**나 그 동의어로 자신을 묘사하지 마라.
41
+ - '~라고 생각합니다', '많은 것을 배웠습니다', '~을 통해 성장했습니다', '귀사' 같은 증거 없는 자기서술 종결구문을 남발하지 마라.
42
+ - 이력서 불릿을 문장으로 바꿔 그대로 반복하지 마라.
43
+ - 회사명을 바꿔도 말이 되는 제너릭 지원동기를 쓰지 마라.
44
+ - 한 통/한 문항에 5~6개 경험을 얕게 나열하지 마라(1~2개 깊게).
45
+ - '규모'(담당 규모·팀 인원·연도)를 '성과'로 위장하지 마라 — 본인 행동의 변화량이 결과다.
46
+ - 없는 성과·수치·고유명사를 지어내거나 과장하지 마라.
47
+ - 공고 키워드를 맥락 없이 나열(keyword stuffing)하지 마라.
48
+ - 나이·성별·사진·가족관계 등 직무무관 개인정보를 넣지 마라.
49
+ - 한 페이지(또는 지정 글자수 상한/하한)를 벗어나거나 빽빽한 텍스트 벽을 만들지 마라.
50
+ - MCP·job_id 같은 기술 용어를 편지 본문/사용자 설명에 노출하지 마라.
51
+
52
+ ### 워크드 예시 (Before → After)
53
+
54
+ 1. **Before:** 저는 책임감이 강하고 성실하며 팀워크가 뛰어난 지원자입니다. 어떤 일이든 열정을 가지고 최선을 다합니다. 귀사에 입사하여 열심히 일하고 싶습니다.
55
+ **After:** [직무 강점] 물류 인턴 시절, 출고 지연이 잦던 야간 피킹 라인을 맡아 동선 재배치와 체크리스트 도입을 주도했고(행동) 3개월간 오배송률을 4.1%→1.2%로 줄였습니다(결과). 같은 '병목을 데이터로 찾아 표준화하는' 방식이 OOO의 풀필먼트 자동화 로드맵에 바로 기여할 수 있다고 봅니다.
56
+ **왜 더 나은가:** 빈 형용사 3개를 STAR-lite 한 단락(행동+전후 델타 4.1→1.2%)으로 교체했고, 두괄식으로 결론을 앞세웠다. 마지막 문장이 회사 고유 맥락(풀필먼트 자동화)과 본인 강점을 연결해 '왜 나·왜 이 회사'를 동시에 충족한다. 회사명을 바꾸면 어색해진다 = 제너릭이 아니다.
57
+
58
+ 2. **Before:** I am writing to apply for the Marketing Coordinator position. I am a hard-working, detail-oriented team player with a passion for marketing and excellent communication skills.
59
+ **After:** When our student org's event registrations stalled at 60 signups, I rebuilt the email funnel and A/B-tested subject lines, lifting registrations to 210 (+250%) in three weeks. That same test-measure-iterate habit is what drew me to Acme's growth team, whose public "experiment weekly" culture matches how I already work.
60
+ **왜 더 나은가:** 상투적 도입과 4개 빈 형용사를 제거하고, **전후 델타(60→210, +250%, 3주)** 가 있는 단일 STAR 사례로 'detail-oriented/communication' 주장을 증명한다. 마지막 절이 회사 고유 근거('experiment weekly' 문화)로 why-this-company를 못박는다.
61
+
62
+ 3. **Before:** 저는 5개 프로젝트를 주도했고 매출 100억 규모 사업을 담당했습니다. 신규 고객을 발굴하고 보고서를 작성했습니다.
63
+ **After:** [직무 강점] 저는 '이탈 직전 고객을 데이터로 식별해 되살리는' 영업입니다. OO기업에서 해지 예고 고객을 결제주기·CS티켓으로 스코어링하는 시트를 만들어 상위 위험군에 선제 제안을 돌렸고(행동) 분기 이탈률을 9%→5%로 낮춰 유지매출 약 1.3억을 방어했습니다(결과). 데이터로 리텐션을 설계하는 이 방식이 OOO의 구독 비즈니스 핵심과 직결된다고 봅니다.
64
+ **왜 더 나은가:** Before는 '5개·100억'이라는 **규모 수치**일 뿐 본인 기여 결과가 0이고 이력서 재진술이다. After는 두괄식 + 이력서가 못 담는 '어떻게(스코어링 시트)' + **본인 행동의 변화량(9→5%, 1.3억)** 을 더하며 회사의 구독 비즈니스와 연결한다. 규모(scale)와 임팩트(impact)의 차이를 보여준다.
65
+
66
+ ## 3. 검증 루브릭 (연결된 AI가 산출물을 이 기준으로 자가검증)
67
+
68
+ 각 항목의 `measure.type`을 정직하게 표기한다 — **`regex`/`count`/`ratio`** 는 LLM 없이 lint로 자동 검사 가능, **`ai-judge`** 는 연결 AI의 의미 판단이 필요(정규식 불가). lint_cover_letter는 `regex`/`count`/`ratio` 항목만 자동 채점하고, `ai-judge` 항목은 연결 AI에게 위임 표시한다.
69
+
70
+ | ID | 검사 항목 | 합격 기준 | 측정 방법(type · LLM 없이 셀 수 있게) |
71
+ |----|-----------|-----------|--------------------------------|
72
+ | R1 | 구조 역할 존재 | 영문: 4역할 present / 한국 문항형: 각 문항 두괄식 + 문항-역량 매핑 present | `ai-judge` — 문단 역할 분류는 의미 판단이라 정규식 불가. 연결 AI가 역할 태그를 달고 누락 0 확인. **lint 자동검사 불가(위임)** |
73
+ | R2 | 제너릭 도입 차단 | 금지 도입 패턴 매치 0건 | `regex` — 첫 문장에 `/(i am writing to apply\|i have always been passionate\|as a recent graduate\|지원하게 되었습니다\|지원합니다\|어릴 적부터\|보며 자랐습니다\|저는 .{0,8}한 사람입니다\|평소 .{0,12}관심이 많아\|to whom it may concern)/i` 히트 = 0 |
74
+ | R3 | 빈 형용사·자기서술 슬롭 | 평가형 형용사/종결구문 사전 매치 0건; 매치 시 동일 문단에 정량 증거 동반 | `regex+ratio` — 사전(성실\|책임감\|열정\|소통을 잘\|꼼꼼\|끈기\|헌신적\|주도적인\|커뮤니케이션이 원활\|라고 생각합니다\|많은 것을 배웠\|통해 성장\|기여하고 싶\|team player\|hard-?working\|detail-?oriented\|motivated\|proactive\|dedicated\|diligent\|people person) 매치=0 권장. **사전은 불완전 — 동의어 우회 가능하므로 R8(형용사+증거 비율)과 함께 본다** |
75
+ | R4 | 정량 **성과**(규모 아님) | 전후 비교/델타 패턴 ≥1 | `regex` — `/\d[\d,\.]*\s?%?\s?(→|->|~|에서)\s?\d[\d,\.]*\s?%?|[+\-]\s?\d+\s?%|(감소|증가|줄였|늘렸|개선|달성)[^.]{0,20}\d/` 매치 ≥1. **연도(20\d\d~20\d\d)·문항번호·전화·날짜는 negative lookahead로 제외** — 단순 숫자 카운트 금지 |
76
+ | R5 | 수치 출처 검증 | 본문 수치 토큰이 저장된 이력서/경력 데이터에 존재 | `count` — 본문 숫자 토큰을 추출해 get_resumes·experiences·projects 텍스트에서 동일/근접 토큰 매칭. 미발견 수치 수 = 0 권장(허위 수치 탐지) |
77
+ | R6 | 회사 고유성 | 회사명/제품/미션 고유명사 ≥2회 + 비종속 검사 | `count`(부분 자동) + `ai-judge`(완전 판정) — 토큰 등장 횟수 ≥2는 카운트 가능. '회사명 placeholder 치환 시 어색해지는 문장 ≥1'은 **연결 AI 판정(위임)** |
78
+ | R7 | 이력서 비반복 | locale별 임계 이하 | `ratio` — 영문: 단어 5-gram 중복 ≤20%. **한국어: 어절 n-gram은 교착어 특성상 부정확 → 임계 신뢰 낮음, 의미 중복은 `ai-judge` 보조 필요(한계 명시)** |
79
+ | R8 | STAR 행동+성과 동반 | 행동동사 단락 중 결과 절 동반 ≥1, 단 '규모≠성과' | `regex`(약) + `ai-judge` — 행동동사+결과신호 동시출현은 카운트되나 '우연 동시출현·규모 수치'를 구분하려면 연결 AI가 'R이 본인 행동의 변화량인가' 판정 |
80
+ | R9 | 분량/글자수 | locale·count_mode별 상·하한 이내 | `count` — 영문 word_count ≤400. 한국: char_count가 지정 limit 이내 **그리고 하한 이상**. **count_mode(with_space\|no_space\|byte) 입력 필수**(미지정 시 fail-safe로 가장 빡빡한 기준 사용) |
81
+ | R10 | 공고 요구 매핑 | 공고 키워드 ≥3개가 증거와 함께 등장 | `count`+`ai-judge` — 토큰 매치 카운트는 가능하나 '증거 동반' 판정은 의미 판단. **`job.requirements`/`keywords`가 비면 skip(N/A)** — 데이터 부재 시 통과/실패 강제 금지 |
82
+ | R11 | 블라인드 가드레일 | 직무무관 개인정보 패턴 0건 | `regex` — `/(\d{2,3}\s?세|남자|여자|아버지|어머니|출신|본적|사진 첨부)/` 등 NCS 금지정보 매치 = 0(locale='ko') |
83
+ | R12 | 1인칭 과다 | '저는/I'로 시작하는 문장 비율 ≤40% | `ratio` — 문장 분리 후 시작 토큰이 (저는\|제가\|^I\b)인 비율 계산 ≤0.40 |
84
+
85
+ **점수·게이팅:** overallPass는 단순 AND가 아니라 **가중 게이팅**이다. **치명(반드시 통과)** = R2·R3·R4·R5·R6(제너릭·증거 없음·허위 수치는 즉시 탈락 사유). **중요** = R1·R8·R10·R11. **경미** = R7·R9·R12(분량 5% 초과 등은 감점만). 치명 항목 중 하나라도 fail이면 overallPass=false. score는 치명 60% + 중요 30% + 경미 10% 가중합. lint는 `regex/count/ratio` 항목만 자동 채점하고 `ai-judge` 항목은 'AI 위임' 상태로 반환한다.
86
+
87
+ **주요 실패 모드:**
88
+ 1. **제너릭·교체 가능**(회사명 바꿔도 말이 됨) — R2·R6로 1차 차단, 비종속 판정은 AI 위임.
89
+ 2. **증거 없는 자기서술**(빈 형용사·종결구문 슬롭, 동의어 우회) — R3 사전 + R8 비율로 이중 방어, 사전 불완전성 명시.
90
+ 3. **규모를 성과로 위장**('100억 담당') — R4·R8이 전후 델타를 요구해 단순 숫자·규모를 거른다.
91
+ 4. **허위 수치 발명**(정량화 압박의 부작용) — R5가 저장 데이터 교차검증.
92
+ 5. **로케일 오적용**(영문 4역할·400단어 규범을 한국 문항형에 강제) — R1·R9가 locale 분기.
93
+ 6. **신입/약점 문항을 일괄 fail** — R4를 약점 문항·신입 경로에서 면제.
94
+
95
+ ## 4. 출처 (Provenance)
96
+
97
+ 신뢰도 등급: **[1차] 대학 커리어센터·공식 기관 / [2차] 커리어 매체·전문 블로그 / [참고] 커뮤니티·기업 블로그(일화적, 인과 주장 약함)**.
98
+
99
+ - **[1차] Harvard FAS — Mignone Center for Career Success** — 직무 직결 1~2개 경험 집중, 특정 수신자 지정, 공고 핵심 요구 연결 · https://careerservices.fas.harvard.edu/resources/harvard-college-guide-to-resumes-cover-letters/
100
+ - **[1차] Georgetown Cawley Career Education Center** — 4문단 구조(훅/자격/회사적합/클로징)와 적합성 1~3문장 · https://careercenter.georgetown.edu/major-career-guides/resumes-cover-letters/cover-letters/
101
+ - **[1차] Princeton Center for Career Development (2019 PDF)** — 문단별 역할 분리, 구체적 사례 vs 일반 진술 · https://careerdevelopment.princeton.edu/sites/g/files/toruqf1041/files/documents/cover_letter_guide_2019.pdf
102
+ - **[1차] University of Cincinnati — Standout Cover Letter Guide (2024)** — 제너릭 도입 금지, 훅 구성, 영문 분량 3/4~1페이지 · https://www.uc.edu/news/articles/2024/11/standout-cover-letter-guide.html
103
+ - **[1차] University of Maryland — Cover Letter Resources** — 회사 미션·가치 리서치 후 본인 경험과 정렬 · https://careers.umd.edu/find-jobs-internships/resumes-cover-letters/cover-letter-resources
104
+ - **[1차] Yale Office of Career Strategy — Cover Letter Guidance** — 공고 정독, 채용담당자 니즈 대응, 전이 가능 스킬(공식 OCS 자료로 인용 권장; studocu 비공식본 대체) · https://ocs.yale.edu/
105
+ - **[1차/기조] NCS 국가직무능력표준 — 블라인드/공정채용 가이드** — 직무무관 개인정보(나이·성별·사진·가족) 배제 기조 (R11 근거) · https://www.ncs.go.kr/
106
+ - **[2차] LiveCareer / CareerAddict / 4 Corner Resources — Cover Letter Mistakes** — 빈 형용사·클리셰 금지, 정량화, 이력서 반복 금지, 분량 · https://www.livecareer.com/resources/cover-letters/basics/cover-letter-mistakes
107
+ - **[2차] Harvard career experts via CNBC** — 'To whom it may concern' 금지·실명 지정(영문 한정) · https://www.cnbc.com/2019/07/23/example-of-the-perfect-cover-letter-according-to-harvard-career-experts.html
108
+ - **[2차] Scale.jobs — Keyword Mistakes in Cover Letters** — 키워드 스터핑 역효과, 키워드는 증거 문장 안에 · https://scale.jobs/blog/common-mistakes-when-using-keywords-in-cover-letters
109
+ - **[참고] Linkareer 두괄식 / 매거진한경 KKK-STAR / 대웅 STAR** — 한국 자소서 두괄식·STAR·정량 지표(일반론으로 유효하나 '합격 패턴' 인과 주장은 일화적) · https://community.linkareer.com/employment_data/4896233
110
+ - **[데이터 사실] CareerMate 코드** — `get_application_context`의 `job.requirements`/`job.keywords`는 optional 자유텍스트 배열(랭킹 없음) · packages/shared/src/schemas.ts:282-283, packages/core/src/context.ts:32-60 (R10 skip 규칙 근거)
111
+
112
+ ## 5. Phase B 힌트 (아키텍처로 연결)
113
+
114
+ - **MCP 도구 아이디어:**
115
+ - `get_cover_letter_playbook(locale?, mode='draft'|'review', question_type?)` — 연결 AI에게 (1) locale별 구조 템플릿(영문 4역할 / ko 문항형), (2) doList/dontList, (3) 금지 형용사·종결구문·도입 사전(ko/en), (4) 루브릭을 머신체크 가능한 형태로 serve. `question_type`(지원동기/성장과정/약점·실패/협업 등)에 따라 약점 문항은 R4 면제 등 **문항별 루브릭 변형**을 반환.
116
+ - `lint_cover_letter(text, job_id?, locale, count_mode?)` — 저장 없이 루브릭을 실제 카운트하는 **LLM-free 정적 검사기**. `regex/count/ratio` 항목만 자동 채점하고 `ai-judge` 항목은 'AI 위임' 상태로 표시. resume/job 컨텍스트는 서버가 get_resumes·get_application_context에서 조회(R5 수치 교차검증, R10 키워드 부재 시 N/A). 통과 후 기존 `save_cover_letter_version`에 저장.
117
+ - **데이터 형태 힌트:**
118
+ ```
119
+ playbook: {
120
+ locale: 'ko'|'en',
121
+ structure: [{ role|questionType, purpose, openingPatternBan:[regex], lengthBudget:{min,max,countMode}, example }],
122
+ bannedAdjectives: { ko:[], en:[] },
123
+ bannedClosers: { ko:[] }, // 종결구문 슬롭
124
+ genericOpenerPatterns: [regex],
125
+ blindGuardrails: [regex], // R11
126
+ rubric: [{ id, check, passBar, severity:'critical'|'major'|'minor',
127
+ measure:{ type:'regex'|'count'|'ratio'|'ai-judge', pattern?, threshold?, llmFree:boolean } }]
128
+ }
129
+ lint 입력: { text, jobId?, locale, countMode:'with_space'|'no_space'|'byte' }
130
+ lint 출력: {
131
+ checks:[{ id, type, llmFree, value, passBar, pass:boolean|'delegated', hits:[{span,snippet}] }],
132
+ score, overallPass, criticalFailures:[id], delegatedToAI:[id] // ai-judge 항목
133
+ }
134
+ ```
135
+ 핵심: 모든 `regex/count/ratio` 측정은 숫자/존재/비율이라 LLM 없이 계산 가능하고, `ai-judge` 항목(R1·R6 비종속판정·R8·R10 증거동반)은 **'LLM-free'라고 광고하지 않고** 연결 AI에 명시적으로 위임한다 — summary의 'even a regex-level check can verify' 과장을 제거한 정직한 분리.
@@ -0,0 +1,121 @@
1
+ # 적합도 매칭 / Fit & Matching — CareerMate 지식 (Phase A)
2
+
3
+ > 이 문서는 CareerMate가 **연결된 AI에게 제공(serve)** 하는 지식이다. CareerMate 안에는 LLM이 없다 — 분석·작성·검증은 연결된 AI(Claude/GPT/Gemini)가 수행하고, 이 플레이북·루브릭은 그 AI가 **세계 최고 수준**으로 일하도록 안내한다.
4
+
5
+ ## 1. 무엇을 하는가
6
+
7
+ 채용공고(JD)와 후보자 증거(이력서·경력) 사이의 **적합도(fit)** 를 분석하는 지식·루브릭이다. 핵심 방법론은 (1) JD를 **must-have(필수)** vs **nice-to-have(우대)** 로 분해하고 복합 요건은 낱개로 쪼개며, (2) 각 요건을 후보자의 구체적 증거(불릿·수치·기간)에 1:1로 매핑하되 **인용은 원문 부분문자열(exact substring)** 로 강제하고, (3) 충족/부분충족/미충족(gap)을 정직하게 분류하며, (4) gap은 숨기지 말고 전이가능 증거·완화 전략으로 다룬다. CareerMate에는 LLM이 없으므로 루브릭은 **LLM 없이 셀 수 있는 형태**(요건 개수, evidence 배열의 비어있음 여부, quotedBullet이 입력의 substring인가, 분수/퍼센트 패턴 존재)로 설계했다. 적합도는 단일 점수가 아니라 **요건별 분해 + must-have 충족률(맥락 신호) + 결정적 갭(critical/hard-gate) 단독 게이트**로 제시한다.
8
+
9
+ ## 2. 플레이북
10
+
11
+ ### 원칙
12
+
13
+ - **(must/nice 명시 라벨링 + 복합 요건 분해)** JD의 모든 요건을 must-have('자격요건'·'minimum'·'required'·'X년 이상'·자격증)와 nice-to-have('우대'·'preferred'·'a plus'·'bonus')로 명시적으로 라벨링하고, 쉼표·'및'·'and'·'or'로 묶인 한 줄(예: 'Python·SQL·통계 지식')은 **개별 요건으로 분해**한 뒤 라벨링한다. nice-to-have 미충족은 탈락 사유가 아니다. _(출처: University Career Centers; NCS 직무수행능력/직업기초능력)_
14
+ - **(증거 1:1 매핑 + 원문 substring 인용 강제)** 각 요건에 후보자 이력서·경력의 **구체적 증거 1개 이상**을 출처 식별자(sourceType·sourceId)와 함께 매핑하고, `quotedBullet`/`quotedMetric`은 **입력 원문의 정확한 부분문자열**로 담는다(의역·요약 금지). 매핑 증거가 없으면 그 요건은 gap이며, 증거를 지어내지 마라. substring 강제는 CareerMate가 LLM 없이 환각·수치변형을 서버측에서 거를 수 있게 하는 핵심 장치다. _(출처: STAR 성과 불릿; AGENTS.md 프라임 디렉티브)_
15
+ - **(의미 매칭은 AI 추론, 표면 키워드는 별도 트랙)** JD 용어와 이력서 표현이 다르면('A/B 테스트'≈'실험 설계') 동의어·상위어로 연결하되, 이 **의미 매칭의 정합성 판단은 연결된 AI의 책임**이며 CareerMate가 검증하지 못한다(루브릭에서 자가검증 항목으로 분리). 동시에 JD 핵심 키워드(고유 기술명·자격증명)가 이력서에 그대로 들어가는지 **표면 존재 O/X**로 별도 보고한다. 키워드는 ATS에서 보통 자동탈락 게이트가 아니라 랭킹·가독성 신호다(방향성만 차용; 구체 % 수치는 출처가 약해 인용하지 않음). _(출처: ATS 실증 정리; O*NET 동의어 매핑은 AI 추론 영역)_
16
+ - **(gap 3단계 처리 + false-negative 방지)** gap을 발견하면: (a) 인접·전이가능 증거가 있으면 **partial로 재분류**하되 '왜 full이 아닌지' 사유 1문장을 필수로 적고, (b) 진짜 없으면 **미충족**으로 정직하게 표기, (c) 미충족 must-have에는 완화 전략(전이가능 경험 강조·학습계획·커버레터 해명) 1개를 붙인다. **gap으로 분류한 must-have마다 인접 증거 탐색을 최소 1회 시도한 흔적**을 남겨, 좋은 후보를 과소평가(false-negative)하지 않는다. _(출처: O*NET KSA 위계는 전이가능성의 참고 프로파일이지 직접 판정 근거 아님 — 전이 판단은 AI 추론)_
17
+ - **(충족률은 맥락 신호, 결정적 갭은 단독 게이트)** must-have 충족률(분자=met인 must 개수; **partial은 분자에서 제외**, 분모=전체 must 개수)을 계산하되, 이는 **합격 신호가 아니라 맥락 신호**다. '약 50~60% 구간부터 면접 콜백이 의미있게 오른다'는 관찰은 지원자 풀의 생존편향이 섞인 상관일 뿐 인과가 아니며, must-have만으로 재정의한 임계값은 별도 캘리브레이션이 없는 휴리스틱이다. **critical(직무 핵심)·hard-gate must-have가 하나라도 gap이면 충족률·60% 무관하게 '지원 권장'을 내지 않는다.** _(출처: TalentWorks 분석(CNBC 2018) — 단일·비피어리뷰, 방향성만 차용)_
18
+ - **(사실·수치·고유명사 보존)** 기간·규모·도구·회사명 등 사실·수치·고유명사는 변형 없이 보존하고, 매핑 시 원문 수치를 그대로(substring) 인용한다. 추정·반올림·과장 금지. _(출처: AGENTS.md 보존 규칙; STAR 정량화)_
19
+ - **(하드 게이트 별도 식별 + ATS knockout 인지)** '경력 N년 이상'·국가자격증·면허·비자·근무지 같은 **하드 게이트**는 별도 표시하고 소프트 스킬로 상쇄되지 않음을 분명히 한다. 이런 binary 요건은 ATS의 knockout/스크리닝 사전질문에서 **실제로 자동탈락되는 경우가 흔하다**(키워드 자동탈락은 드물어도 구조화 사전질문 탈락은 흔하다). 따라서 '자동탈락은 드뭄'을 하드 게이트에 일반화하지 마라. _(출처: O*NET 규제요건; NCS 자격요건; ATS knockout 실무)_
20
+ - **(범위 한계 명시 + 오버퀄/방향 불일치)** 이 분석은 '증거로 매핑 가능한 하드 요건' 중심이며, 협업·커뮤니케이션 같은 **soft/culture fit는 다루지 않음을 명시**한다(적합도 ≠ 합격가능성). 또한 미달뿐 아니라 **오버퀄(시니어가 주니어 JD 지원)·커리어 방향 불일치**도 리스크로 표기한다. _(출처: 채용 매니저 실무; O*NET은 soft 신호 판정 도구 아님)_
21
+
22
+ ### Do
23
+
24
+ - 분석 시작 전 `get_application_context`를 호출해 프로필·대표 이력서·경력·스킬·대상 공고를 한 번에 확보한다(맥락 없이 분석 금지).
25
+ - JD의 모든 요건을 한 줄씩 추출하고 **복합 줄은 낱개로 분해**한 뒤 표로 만든다. 각 줄에 [필수/우대], [critical 여부], [hardGate 여부], [매핑 증거 출처 ID 또는 GAP]을 단다.
26
+ - 각 매핑 증거는 실제 불릿·경력을 **원문 substring으로 인용**하고, 수치는 그대로 옮긴다.
27
+ - must-have 충족률(met must 수 / 전체 must 수, **partial 제외**)을 계산해 **맥락 신호**로 제시하되, critical·hardGate gap이 있으면 '권장 불가'를 병기한다.
28
+ - 미충족 must-have마다 완화 전략 1개를 적고, gap으로 분류한 must마다 인접 증거 탐색 시도 흔적을 남긴다.
29
+ - JD 핵심 키워드(기술명·자격증·도구)의 이력서 표면 존재 O/X를 의미 매칭과 분리해 별도 점검한다.
30
+ - 저장된 이력서/JD가 바뀌면 분석이 낡으므로, 분석에 **근거가 된 이력서 버전 ID·JD 식별자**를 기록해 재분석 트리거를 남긴다.
31
+ - 결과는 `save_fit_analysis`로 저장하고 대시보드 링크(http://127.0.0.1:4319)를 안내한다.
32
+ - 기술 용어(must-have, ATS, hard-gate 등)는 쉬운 한국어로 풀어 설명한다.
33
+
34
+ ### Don't
35
+
36
+ - JD에 없는 요건을 추가하거나, 없는 경력·수치를 지어내 gap을 메우지 마라(환각 금지).
37
+ - 우대(nice-to-have) 미충족을 탈락 사유처럼 다루거나 점수를 깎지 마라.
38
+ - 증거 인용 없이, 또는 의역·요약 인용으로 '충족' 판정하지 마라(인용은 원문 substring).
39
+ - 충족률 60%를 '합격 신호'나 '권장 게이트'로 격상하지 마라 — 맥락 신호다. 100%까지 채우라고 압박하지도 마라.
40
+ - critical·hard-gate(면허·연차·비자·근무지·필수자격증) 미충족을 소프트 스킬로 상쇄해 '지원 권장'을 내지 마라.
41
+ - partial을 '왜 full이 아닌지' 사유 없이 남발해 충족률을 인위적으로 부풀리지 마라.
42
+ - JD의 'required' 라벨을 무비판적으로 신뢰하지 마라 — 요건 인플레이션(특히 연차·학위)을 인지하고, 의심되면 사용자에게 알린다.
43
+ - 사실·수치·고유명사를 반올림·과장·변형하지 마라.
44
+ - 데이터를 외부로 보내거나 웹에서 후보자 정보를 검색하지 마라(모든 데이터는 `~/.careermate` 로컬).
45
+ - gap을 숨기거나 얼버무리지 마라 — 정직하게 미충족으로 표기하고 완화책을 제안하라.
46
+
47
+ ### 워크드 예시 (Before → After)
48
+
49
+ 1. **Before:** JD 요건 'SQL 기반 데이터 분석 경험' → "데이터 분석 잘하실 것 같아요. 적합합니다." (증거·출처 없음, 추정)
50
+ **After:** 요건 'SQL 기반 데이터 분석' [필수·critical] → 충족. 근거 `{sourceType:resume, sourceId:1, quotedBullet:"주간 매출 대시보드를 SQL로 추출·집계해 12개 캠페인 ROI를 비교, 광고비 18% 재배분"}`(원문 substring). 정확 키워드 'SQL' 이력서 표면 존재(O).
51
+ **왜 더 나은가:** 추정·칭찬 대신 실제 불릿을 출처 ID + **원문 substring**으로 인용했다. CareerMate가 LLM 없이 'quotedBullet이 입력 이력서의 부분문자열인가'를 검증할 수 있고, 키워드 표면 존재는 별도 점검해 환각 여지가 없다.
52
+
53
+ 2. **Before:** JD 'PM 3년 이상' 미충족인데 마케팅 경력을 'PM 유사 경험'으로 뭉뚱그려 '충족'으로 표기, 충족률 5/8(62%)로 '60% 상회 → 지원 권장'.
54
+ **After:** 요건 'PM 경력 3년 이상' [필수·hardGate] → 미충족. PM 직함 0년, 마케팅 4년. 완화: 마케팅 중 '신규 기능 베타 운영·우선순위 결정'을 인접 증거로 강조 가능하나 '3년'은 연수 게이트라 상쇄 불가. 커버레터에서 전환 의지 해명 권장. **종합 판정: hard-gate 미충족으로 권장 불가** — 충족률(5/8=62%)은 참고용 맥락 신호이며 권장 근거가 아니다.
55
+ **왜 더 나은가:** hard-gate를 소프트 경험으로 덮지 않았고, 60% 충족률을 '권장 근거'로 쓰지 않았다. 충족률 옆에 '권장 불가'를 강제 병기해 FM-04(충족률)와 FM-05(하드게이트)의 산술 충돌을 제거했다.
56
+
57
+ 3. **Before:** "전반적으로 잘 맞습니다(80점)." (요건별 분해·근거 없음, 단일 점수)
58
+ **After:** 적합도 요약 — 필수 8개 중 met 6 / partial 0 / gap 2, 충족률 6/8(75%, partial 제외). 우대 4개 중 1개 충족. 충족 must: [Python(resume#2 불릿), API 설계(experience#4 불릿)]. 미충족 must: [AWS 운영경험 → GCP 경험으로 부분대체 가능(전이, partial 후보지만 'AWS 특화 운영툴 경험 없음'으로 gap 유지), 정보처리기사 → **hardGate 여부 확인 필요**: JD가 '필수'면 권장 불가/'우대'면 가점]. critical·hardGate gap 없음 가정 시에만 충족률을 권장 맥락으로 사용. 보강 1순위: AWS 키워드/경험 명시.
59
+ **왜 더 나은가:** 단일 점수 대신 met/partial/gap을 분해하고 partial 계수 규칙을 명시했다. 자격증의 게이트/가점 판별을 '확인 필요'로 명시해 예시 내 모순(가점 vs 하드게이트)을 제거했다.
60
+
61
+ ## 3. 검증 루브릭 (연결된 AI가 산출물을 이 기준으로 자가검증)
62
+
63
+ | ID | 검사 항목 | 합격 기준 | 측정 방법(LLM 없이 셀 수 있게) |
64
+ |----|-----------|-----------|--------------------------------|
65
+ | R1 | 모든 요건에 [필수/우대] 라벨 + 복합 요건 분해 | 라벨 누락 0개; 쉼표·'및'·'and/or'로 묶인 줄이 개별 항목으로 분리됨 | 추출 항목 수를 세고 각 항목에 'must'/'nice' 토큰 존재 확인(누락==0). 원문에서 구분자 포함 줄 수 대비 분해 항목 수가 ≥ 구분자+1 인지 검사 |
66
+ | R2 | 충족·부분충족 판정에 출처 ID + evidence 존재 | status가 met·partial인데 evidence[] 배열이 빈 항목 0개 | (서버 검증 가능) met·partial 항목 수 대비 `evidence.length>0` 항목 수 비율 == 100% |
67
+ | R3 | quotedBullet/quotedMetric이 원문 substring (환각·수치변형 차단) | 인용 문자열이 해당 sourceId 입력 텍스트의 부분문자열이 아닌 항목 0개 | (서버 검증 가능) 각 evidence의 quotedBullet을 입력 이력서/경력 텍스트에 대해 indexOf/`includes` 문자열 검색 → 미발견 개수 == 0 |
68
+ | R4 | gap 표기 + must-have 미충족마다 완화 전략 | 미충족 must 중 mitigation 문장이 없는 항목 0개 | 미충족 must 개수 == mitigation 문장 개수 비교 |
69
+ | R5 | must-have 충족률 수치 제시 + partial 제외 규칙 | 'met must 수 / 전체 must 수' 분수·% 1개 이상; 분자에 partial 미포함 | 분수/% 정규식(예: `\d+/\d+`, `\d+%`)이 must 문맥과 함께 1회 이상; 분자 == status=='met' 개수와 일치 확인 |
70
+ | R6 | critical·hardGate gap 시 '권장 불가' 병기 (게이트 단독 우선) | hardGate 또는 critical이 gap인데 verdict가 'recommend'인 사례 0개 | (서버 검증 가능 — 경고 아닌 **거부**) `requirements`에 `hardGate&&status==gap` 또는 `critical&&status==gap`이 1개라도 있으면 `verdict=='recommend'` 금지 |
71
+ | R7 | 키워드 표면 존재가 의미 매칭과 분리 보고 | JD 핵심 키워드별 'O/X' 표기 1개 이상, 의미 매칭 충족 판정과 별도 필드 | 출력에 `keywordSurfacePresent` 또는 'O/X·있음/없음' 항목 카운트 ≥ 1 |
72
+ | R8 | partial 남용 방지 (사유 강제) | partial 항목 중 '왜 full이 아닌지' 사유 문장이 없는 항목 0개 | partial 항목 수 == partialReason 문장 수 비교 |
73
+ | R9 | gap 과소평가(false-negative) 방지 | gap으로 분류한 must마다 인접 증거 탐색 시도 흔적 존재 | gap must 개수 대비 `transferAttempt` 표기(예: "인접 검토: …") 항목 수 == 100% |
74
+ | R10 | 신선도 추적 | 분석에 근거가 된 이력서 버전 ID·JD 식별자가 기록됨 | 출력/페이로드에 `resumeVersionId`·`jobId`(또는 JD 해시) 필드 존재 여부 == 있음 |
75
+
76
+ **의미 매칭·전이가능성은 LLM 없이 검증 불가** → R2·R3·R5·R6은 CareerMate 서버가 LLM 없이 강제(존재 여부·substring·산술·게이트). 반면 '의역 동의어 매칭이 타당한가', '전이가능성 판단이 옳은가', '요건 추출이 빠짐없는가'는 **외부 AI의 셀프체크 책임**이며 서버가 보증하지 않는다(R1·R4·R8·R9는 형식 카운트만 강제, 내용 타당성은 AI 책임).
77
+
78
+ **주요 실패 모드:**
79
+ - (과대평가) 의역 인용으로 충족 위장 → R3 substring 강제로 차단.
80
+ - (충족률 조작) 복합 요건 미분해로 분모 축소(R1), partial을 분자에 넣어 부풀림(R5), partial 남발(R8).
81
+ - (오권장) hard-gate·critical gap을 충족률로 덮어 'recommend' → R6 서버 거부.
82
+ - (과소평가, 가장 비싼 실패) 전이가능 강점을 못 알아보고 gap으로 깎아 좋은 후보 자기검열 → R9.
83
+ - (낡은 분석) 이력서/JD 갱신 후 옛 분석 재사용 → R10.
84
+
85
+ ## 4. 출처 (Provenance)
86
+
87
+ - **O*NET Content Model — U.S. DOL / National Academies** — KSA(지식·스킬·능력) 택소노미와 자격·면허 같은 규제요건 분류의 참고 프로파일. 단, '스킬 A→B 전이가능성'을 직접 판정하지는 않음(전이 판단은 AI 추론). https://www.onetcenter.org/database.html
88
+ - **University Career Centers (Arizona, WVU, Duke, Michigan)** — JD를 자격요건(필수)·책임·개요로 분해, 필수 vs 우대 우선순위, 키워드 미러링·고용주 우선순위 정렬. https://career.arizona.edu/resources/tailoring-your-resume/
89
+ - **ATS 실증 정리 (ResumeAdapter; The Interview Guys)** — '키워드는 자동탈락 게이트가 아니라 랭킹·가독성 신호'라는 **방향성만** 차용(이력서 첨삭 상품 사이트로 1차 연구 아님; '+40% 검토율'·'자동탈락 8%' 같은 구체 % 수치는 출처가 약해 본문 정량 주장으로 쓰지 않음). 단 비자·자격·근무지 같은 knockout 사전질문은 실제 자동탈락이 흔하다는 점을 하드 게이트에 반영. https://www.resumeadapter.com/ats-statistics
90
+ - **TalentWorks 분석 (CNBC 2018, InHerSight)** — '요건 ~50-60% 충족부터 면접 콜백이 오른다'는 관찰. 단일·비피어리뷰·생존편향 가능이라 **인과가 아닌 맥락 신호**로만 사용(must-have 전용 60% 임계값은 별도 캘리브레이션 없는 자작 휴리스틱임을 명시). https://www.cnbc.com/2018/12/12/matching-half-of-a-jobs-requirements-might-still-get-you-an-interview.html
91
+ - **Behavioural Insights Team — 젠더 지원격차** — 이 출처의 실제 결론은 '여성은 100% 충족 시에만 지원' **신화를 반박**한다(실제 격차는 여성 56% vs 남성 52%로 미미). 따라서 '100% 충족 압박은 불필요'의 근거로 인용하되, '여성만 자기검열' 단정은 사용하지 않음(경향성 가설로 수위 조정). https://www.bi.team/blogs/women-only-apply-when-100-qualified-fact-or-fake-news/
92
+ - **STAR 기반 성과 불릿 (Columbia CCE, ResumeBuilder, TopResume)** — 증거→주장 매핑, 정량화 수치 보존, 행동-결과 구조 → 증거 인용·수치 보존 원칙. https://www.resumebuilder.com/career-center/star-method-resume/
93
+ - **NCS 국가직무능력표준 — HRD Korea** — 직무기술서 기반 능력중심채용, **직무수행능력(능력단위)·직업기초능력 구분**(한국 맥락의 필수/우대·하드요건 분류). 'on-spec'은 NCS 표준 용어가 아니라 사용하지 않음. https://www.ncs.go.kr/index.do
94
+
95
+ ## 5. Phase B 힌트 (아키텍처로 연결)
96
+
97
+ - **MCP 도구 아이디어:** `get_fit_analysis_guide` — 연결된 AI가 적합도 분석 직전 호출하면 (1) 요건 분해·복합 요건 분리 체크리스트, (2) 증거-매핑 템플릿(substring 인용 규칙 포함), (3) R1~R10 셀프-체크 루브릭, (4) 60% '맥락 신호' 규칙·critical/hardGate 단독 게이트 규칙을 구조화 JSON으로 반환. `save_fit_analysis`는 `requirements[]` 구조를 입력받아 **LLM 없이** 충족률·갭 개수를 서버측에서 재계산·검증한다.
98
+ - **데이터 형태 힌트:**
99
+ ```
100
+ {
101
+ jobId, resumeVersionId, // R10 신선도
102
+ fitSummary: { mustHaveTotal, mustHaveMet, // mustHaveMet = status=='met' 개수만 (partial 제외)
103
+ mustHaveMetRate, niceToHaveMet,
104
+ verdict: 'recommend'|'conditional'|'not_recommend',
105
+ overqualified: bool }, // 오버퀄/방향 불일치 플래그
106
+ requirements: [ {
107
+ id, text, type:'must'|'nice',
108
+ critical: bool, hardGate: bool, // 단독 게이트
109
+ status: 'met'|'partial'|'gap',
110
+ partialReason?, // partial이면 필수 (R8)
111
+ transferAttempt?, // gap must면 필수 (R9)
112
+ evidence: [ { sourceType:'resume'|'experience', sourceId,
113
+ quotedBullet, // 입력 원문의 exact substring (R3)
114
+ quotedMetric? } ],
115
+ keywordSurfacePresent: bool, // R7 표면 트랙
116
+ mitigation? // 미충족 must면 필수 (R4)
117
+ } ],
118
+ generatedBy: 'claude'|'gpt'|'gemini'
119
+ }
120
+ ```
121
+ **서버측 검증(LLM 불요):** ① `status∈{met,partial}`인데 `evidence[]` 빈 항목 → **거부**(R2). ② 각 `quotedBullet`이 해당 sourceId 입력 텍스트의 부분문자열이 아니면 → **거부**(R3). ③ `mustHaveMet`를 status=='met' 개수로 재계산(클라이언트 자기보고 불신, R5). ④ `hardGate&&status==gap` 또는 `critical&&status==gap`이 1개라도 있는데 `verdict=='recommend'` → **거부**(경고 아님, R6). ⑤ partial인데 `partialReason` 없음(R8)·gap must인데 `transferAttempt` 없음(R9)·미충족 must인데 `mitigation` 없음(R4) → 거부.
@@ -0,0 +1,118 @@
1
+ # 사람처럼 쓰기 (anti-AI-slop) / Human Writing — CareerMate 지식 (Phase A)
2
+
3
+ > 이 문서는 CareerMate가 **연결된 AI에게 제공(serve)** 하는 지식이다. CareerMate 안에는 LLM이 없다 — 분석·작성·검증은 연결된 AI가 수행하고, 이 플레이북·루브릭은 그 AI가 **세계 최고 수준**으로 일하도록 안내한다.
4
+
5
+ ## 1. 무엇을 하는가
6
+
7
+ 커리어 문서(자기소개서·자기 PR·지원 메일·면접 답변)를 "AI가 쓴 티" 없이, 사용자 고유의 목소리로, 사실을 보존하며 쓰도록 연결된 AI를 안내한다. CareerMate의 **1차 사용자층은 한국어 자소서 작성자**이므로 이 플레이북은 한국어 슬롭(번역투·클리셰·기계적 병렬·수동태)을 1차 기준으로, 영어 마커는 영문 지원서일 때만 적용하는 **보조 기준**으로 둔다. 이 문서는 기존 `packages/prompts/src/humanize.ts`의 정성 가이드(한국어 8개 항목, `epoko77-ai/im-not-ai` 근거)를 **상위 단일 원본으로 흡수·확장**하고, 거기에 "LLM 없이 셀 수 있는" 결정론 루브릭과 채용 적합성 축을 더한 것이다. 핵심은 슬롭 제거가 아니라 **"거짓 없고 직무에 맞닿은, 사람 목소리의 글"**을 만드는 것이다 — 슬롭이 0이어도 동문서답·내용 공백이면 떨어진다.
8
+
9
+ ## 2. 플레이북
10
+
11
+ ### 원칙
12
+
13
+ - **(한국어 슬롭을 1차로 거른다)** 번역투("~에 대한/~을 통해/~에 있어서/~라는 점에서/가지고 있습니다/~을 진행하였습니다"), 클리셰("급변하는 시대/4차 산업혁명/끊임없는 노력/귀사의 발전에 기여/소통과 협업/성장하는 인재"), 정의문 반복("저는 ~한 사람입니다"의 남발), 수동태("~되어졌습니다"), 형식 과용(가운뎃점 `·` 남발, 불필요한 굵게/이모지, "첫째·둘째·셋째")을 제거한다 — 이것이 한국 채용 담당자가 실제로 거르는 진짜 슬롭이다. _(출처: humanize.ts / epoko77-ai/im-not-ai)_
14
+ - **(영어 과잉어휘는 영문 지원서에서만 보조로 차단)** delve, leverage, utilize, showcase, underscore, harness, bolster, illuminate, facilitate, intricate, meticulous, tapestry, realm, beacon, testament, foster, robust 등은 같은 의미의 일상어로 치환한다(leverage→use, utilize→use, delve into→examine). 단 단어 경계(`\b`)로 매칭하고 정당한 기술 맥락(`robust error handling`, UI `navigate`, `foster care`)은 예외로 둔다. **locale='ko'에서는 이 사전의 가중치를 낮춘다.** _(출처: Kobak et al. 2024; The Conversation 2025 — 단, "단일 지표 맹신은 과학보다 art"라는 원문 경고를 함께 적용)_
15
+ - **(증거로 보여준다, Show don't tell)** 열정 선언("열정을 가지고/최선을 다하겠습니다/빨리 배웁니다/I am excited to/I want to/fast learner/great fit")과 추상 성격 나열("성실·책임감·소통능력")은 **무엇을 했고 그 결과 수치가 어떻게 됐다**는 구체 사실로 대체한다. _(출처: TopResume; The Muse; Univ. of Michigan Career Center; humanize.ts 7항)_
16
+ - **(사실을 잠근다, Fact lock)** 숫자·고유명사·날짜·직함·회사명·기술스택은 사용자가 준 그대로 보존한다. **단, 입력 사실로부터의 명시적 파생연산(차·합·비율 환산: 월12건→월2건에서 "83% 감소")은 허용**한다. 모르면 지어내지 말고 `[확인 필요]`로 표시한다. 이 체크는 한국어 NER 한계 때문에 **결정론 게이트가 아니라 LLM 보조 플래그**로 둔다(아래 R7). _(출처: CareerMate AGENTS.md 프라임 디렉티브)_
17
+ - **(직무 적합성을 1차 게이트로)** 주장 1개당 **그 JD의 요구 역량과 매칭되는** 검증 가능한 사실 1개를 붙인다. `get_application_context`의 `matched_keywords`/`missing_keywords`와 산출물을 대조해, 슬롭은 없지만 동문서답인 글을 거른다. _(출처: 채용 매니저 리뷰 — job-fit 축; CareerMate get_application_context)_
18
+ - **(목소리 보존)** 사용자 원문·이력서를 샘플로 평균 문장길이·어휘 수준을 맞추고, 표준 코퍼레이트 톤으로 평탄화하지 않는다. 이는 분포 유사도로 측정 가능하다(R8). _(출처: The Augmented Educator; humanize.ts; get_writing_style_guide)_
19
+ - **(간결성, Omit needless words)** 형용사·부사로 부풀리지 않고, 초안 후 "불필요한 단어 삭제" 패스를 1회 더 돌린다. 능동태를 기본으로 한다. _(출처: Strunk & White)_
20
+ - **(두괄식 + STAR)** 각 문항 첫 문장에 그 문항의 핵심 결론을 두고, 본문은 상황(S)·과제(T)·행동(A)·결과(R)로 전개한다. **한국어에서 "저는 ~입니다"로 시작하는 두괄식 대표문장은 정석이므로 슬롭으로 취급하지 않는다.** _(출처: 링커리어/하이잡/대웅 STAR 가이드)_
21
+
22
+ ### Do
23
+
24
+ - 문항/문단 첫 문장에 핵심 결론을 둔다(두괄식). "저는 데이터로 문제를 정의하는 사람입니다" 같은 대표문장은 권장된다.
25
+ - 주장 1개당 **그 JD 요구역량에 맞닿은** 검증 가능한 사실(수치·기간·도구·역할·결과)을 최소 1개 붙인다.
26
+ - `matched_keywords`를 산출물이 증거와 함께 다루는지 확인한다(키워드 커버리지).
27
+ - 능동태·단문 위주로 쓰되 문장 길이를 변주한다(짧은 문장과 긴 문장 섞기). 단 이는 신호일 뿐 목표가 아니다 — 가독성 우선.
28
+ - 공고/플랫폼의 글자수 상한(예: 500자/1000자)을 지킨다. 초과는 시스템에서 잘린다.
29
+ - 사용자 원문·이력서의 어조·어휘 수준을 샘플로 삼아 목소리를 맞춘다.
30
+ - 숫자·고유명사·날짜·회사명을 원본과 대조하되, 콤마/단위/한글수사 차이(1,200ms=1200ms, 12만=120,000)는 같은 값으로 정규화한다.
31
+ - 입력 사실에서 파생한 환산값(차·합·비율)은 계산해 써도 된다.
32
+ - 초안 후 "불필요한 단어 삭제" 패스를 1회 더 돌린다.
33
+ - 불확실한 사실은 `[확인 필요]`로 표시하고 사용자에게 되묻는다.
34
+
35
+ ### Don't
36
+
37
+ - 번역투("~에 대한/~을 통해/가지고 있습니다")와 클리셰("급변하는 시대/4차 산업혁명/귀사의 발전에 기여")로 문장을 채우지 않는다.
38
+ - "성실·책임감·소통능력" 같은 추상 형용사를 사례 없이 나열하지 않는다.
39
+ - "열정을 가지고/최선을 다하겠습니다/밑거름이 되겠습니다/I am excited to/I want to(공허한 자기선언)"로 채우지 않는다.
40
+ - **회사명 오기재**(타 회사 자소서 복붙)를 하지 않는다 — fact-lock보다 흔하고 치명적이다.
41
+ - **문항 질문에 답하지 않는 동문서답**을 하지 않는다.
42
+ - 가운뎃점(`·`) 남발, 불필요한 굵게/이모지, 과한 마크다운, em-dash 남발을 하지 않는다.
43
+ - "A, B, and C / A하고 B하며 C하는" 삼단열거를 **기계적으로** 반복하지 않는다(정상적 명사 3항 나열 "디자인·개발·운영"은 허용).
44
+ - "it's important to note/물론 ~지만/전반적으로/어떻게 보면" 헤징·메타 코멘트를 넣지 않는다.
45
+ - **출처 없는 정성 우월 주장**("팀 사기를 크게 높였다/탁월한/대폭 개선")을 쓰지 않는다 — 숫자가 없어 fact-lock에도 안 걸리지만 면접에서 깨진다.
46
+ - 사용자가 주지 않은 수치·수상·직함을 추정·미화·반올림하지 않는다(파생 환산은 예외).
47
+ - 사용자 고유 표현을 표준 코퍼레이트 톤으로 평탄화하지 않는다.
48
+
49
+ ### 워크드 예시 (Before → After)
50
+
51
+ 1. **Before(한국어):** "저는 어떤 일이든 성실하고 책임감 있게 임하며, 끊임없는 열정으로 귀사의 무한한 가능성에 발맞춰 일익을 담당하고자 합니다. 다양한 경험을 통해 소통 능력과 문제 해결 능력을 길렀습니다."
52
+ **After:** "재고 데이터 정합성 문제로 월 평균 12건의 오배송이 발생하던 물류팀에서, 저는 주문-재고 대조 스크립트를 직접 만들어 야간 배치에 넣었습니다. 그 결과 오배송은 3개월 만에 월 2건으로(약 83% 감소) 줄었고, CS 문의도 40% 감소했습니다."
53
+ **왜 더 나은가:** Before는 추상 성격 나열·클리셰("무한한 가능성/일익을 담당")뿐이라 누구나 복붙 가능하다. After는 STAR로 상황(월12건)·행동(스크립트·야간배치)·결과(월2건, CS 40%↓)를 수치로 보여준다. "83%"는 입력 12→2의 **허용된 파생 환산**이라 fact-lock을 위반하지 않는다.
54
+
55
+ 2. **Before(한국어, 번역투):** "이번 프로젝트에 있어서 저는 데이터 분석에 대한 역량을 가지고 있으며, 이를 통해 리텐션 개선을 진행하였습니다. 또한 협업 능력도 갖추고 있습니다."
56
+ **After:** "마케팅 로그 12만 건을 SQL로 분석해 이탈 구간을 찾았고, 리텐션을 8%p 올렸습니다. 인턴 2명을 온보딩하며 분석 대시보드 표준을 만들었습니다."
57
+ **왜 더 나은가:** Before는 번역투("~에 있어서/~에 대한/~을 통해/가지고 있으며/진행하였습니다")와 "~을 갖추고 있습니다" 정의문이 골격이다. After는 번역투를 걷어내고 두 개의 구체 성과(수치 포함)로 능동태 단문을 쓴다. 정보는 늘고 길이는 줄었다.
58
+
59
+ 3. **Before(영문 지원서):** "I am thrilled to leverage my robust skill set to delve into new challenges and showcase my ability to navigate complex environments—driving innovation, fostering collaboration, and underscoring my passion for excellence."
60
+ **After:** "I led the checkout-API rewrite for 3 engineers over 4 months. We cut p95 latency from 1,200ms to 380ms and reduced payment errors by 27%. I want to bring that same focus to your payments team."
61
+ **왜 더 나은가:** Before는 영어 과잉어휘(leverage/delve/showcase/navigate/foster/underscore)·em-dash·삼단열거·빈 열정어가 전부라 사실이 0개다. After는 역할·기간·인원·전후 수치로 능동 단문을 쓴다. (영문일 때만 영어 lexicon이 1차로 작동한다.)
62
+
63
+ ## 3. 검증 루브릭 (연결된 AI가 산출물을 이 기준으로 자가검증)
64
+
65
+ > **캘리브레이션 경고:** 아래 임계값(em-dash 2개, 사실토큰, 문장길이 표준편차 등)은 주로 영어 코퍼스에서 온 **잠정 수입품**이다. Phase B에서 한국어 합격 자소서 코퍼스로 percentile 캘리브레이션하고 분기별 재조정해야 한다. lexicon은 후행 지표(모델 RLHF가 tell을 학습해 회피 중)이므로 **버전·출처일자를 필수로 기록**한다. 모든 카운트 임계는 "하드 fail"이 아니라 "신호" 우선이며, 게이트로 쓰는 것은 R5·R6·R9뿐이다.
66
+
67
+ | ID | 검사 항목 | 합격 기준 | 측정 방법(LLM 없이 셀 수 있게) |
68
+ |----|-----------|-----------|--------------------------------|
69
+ | R1 | 한국어 슬롭 사전 매칭(번역투·클리셰·수동태) | 매칭 0건(있으면 치환 제안+사람 판단). **soft** | locale='ko' 사전(번역투 "~에 대한/~을 통해", 클리셰 "급변하는 시대/4차 산업혁명/귀사의 발전에 기여", "~되어졌습니다")으로 부분문자열 매칭, 히트 카운트 |
70
+ | R2 | 영어 과잉어휘(영문 지원서 한정) | locale='en'일 때만 적용, 치환 제안. **soft** | 단어경계 `\b(delve|leverage|utilize|showcase|...)\b` 정규식, 기술맥락(robust error handling 등) 화이트리스트 예외. locale='ko'면 가중치↓ |
71
+ | R3 | 형식 tell(가운뎃점·이모지·굵게·em-dash) | 가운뎃점 남발·이모지 0, em-dash≤2(영문만 변별력). **soft** | `·` `—` 이모지 유니코드·`**` 출현 카운트. (한국어 자소서에서 em-dash 변별력은 사실상 0 — 가운뎃점이 더 중요) |
72
+ | R4 | 헤징/메타 코멘트 | 매칭 0건. **soft** | 사전("it's important to note/물론/전반적으로/어떻게 보면") 부분문자열 매칭 카운트 |
73
+ | R5 | 빈 열정어·자기선언 상투구 | 매칭 0건(있으면 각 1개를 구체 사실로 대체). **gate** | 사전("열정을 가지고/최선을 다하겠습니다/빨리 배웁니다/I am excited to/I want to/fast learner/great fit") 매칭 카운트 |
74
+ | R6 | 증거 밀도(주장당 사실) | 주장 1개당 사실 토큰(숫자/%/기간) ≥1. **gate**(1차 게이트) | 한국어=어절 기준, 영어=word 기준으로 분리. 숫자 `\d`, `%`, 기간 `\d+\s*(년\|개월\|주\|month\|year)` 카운트. 한국어 "대문자 고유명사"는 세지 않음 |
75
+ | R7 | 사실 잠금(fact-lock) | 입력에 없는 숫자·고유명사 0건(파생 환산 제외). **LLM 보조 플래그**(게이트 아님) | 숫자 정규화(콤마/단위/한글수사: 1,200ms=1200ms, 12만=120,000) 후 차집합. 차/합/비율 화이트리스트. 한국어 고유명사는 NER 없이 못 잡으므로 연결된 AI가 최종 판정 |
76
+ | R8 | 목소리 보존(평탄화 금지) | 산출물 평균 문장길이가 사용자 원문 샘플 ±30% 이내, TTR 유사. **soft** | 사용자 원문 샘플과 산출물의 평균 문장길이 차이·어휘다양성(TTR) 비교. 순수 산술 |
77
+ | R9 | 글자수 상한 | 공고/플랫폼 max_chars 이하. **gate** | `text.length` ≤ max_chars. 가장 객관적인 결정론 체크 |
78
+ | R10 | 직무 키워드 커버리지 | `matched_keywords` 중 산출물이 증거와 함께 다루는 비율 ≥ 목표치. **soft** | get_application_context의 keyword 집합과 산출물 토큰 교집합 비율 |
79
+ | R11 | 회사명 정합 | 산출물의 회사명 = 대상 공고 회사명. **gate** | 공고의 company 문자열이 산출물에 존재, 타 회사명 부재 확인(타 회사 복붙 탐지) |
80
+ | R12 | 문장 길이 변주(burstiness) | 문장 ≥6개일 때만 적용, 표준편차 ≥5단어. **soft(신호일 뿐 목표 아님)** | 문장 분리 후 단어수 표준편차. 짧은 문항(<6문장)은 통계 무의미하므로 미적용 |
81
+
82
+ **주요 실패 모드:**
83
+ 1. **동문서답·직무 무관** — 슬롭이 0이어도 JD와 무관한 자랑이면 떨어진다(R6·R10·채용 1차 탈락 사유).
84
+ 2. **회사명 오기재·글자수 초과** — 결정론으로 가장 쉽게 잡히는 치명적 실수인데 자주 누락된다(R9·R11).
85
+ 3. **환각·출처 없는 정성 과장** — 입력에 없는 수치/수상, 또는 숫자 없는 "크게/탁월한" 정성 주장. 면접에서 즉시 발각(R7 + Don't의 정성 주장 금지).
86
+ 4. **false-positive 오탈락** — 영어 사전을 한국어에 그대로 적용, 정상 3항 명사나열을 삼단열거로 오탐, 짧은 문항에 burstiness 강제. 이를 막으려 게이트는 R5·R6·R9·R11로 한정하고 나머지는 soft 신호로 둔다.
87
+ 5. **사전 시효성(adversarial drift)** — 2024 'delve' 통계는 후행 지표. 버전 미기록·미캘리브레이션 lexicon은 정상 글을 오탈락시킨다.
88
+
89
+ ## 4. 출처 (Provenance)
90
+
91
+ - **humanize.ts / epoko77-ai/im-not-ai** — 한국어 AI-tell 분류(번역투·클리셰·기계적 병렬·수동태·형식 과용)의 1차 근거. **이 문서의 한국어 ban-list 본체.** (`packages/prompts/src/humanize.ts`, MIT License)
92
+ - **Kobak et al., "Delving into LLM-assisted writing…"** — 영어 과잉어휘 사전의 실측 근거(delve +1500% 등). **단 영문 지원서 한정 보조 기준**으로만 적용. · https://arxiv.org/abs/2406.07016
93
+ - **The Augmented Educator, "Ten Telltale Signs of AI-Generated Text"** — 헤징·정형 템플릿(2~5배)·낮은 burstiness·장식 명사·개인 목소리 부재. dontList 다수 근거. · https://www.theaugmentededucator.com/p/the-ten-telltale-signs-of-ai-generated
94
+ - **The Conversation, "Too many em dashes? … Spotting text written by ChatGPT" (2025)** — em-dash 일화적 근거이자 **"단일 지표 맹신은 과학보다 art"라는 한계 경고** — R3을 soft로 강등한 근거. · https://theconversation.com/too-many-em-dashes-weird-words-like-delves-spotting-text-written-by-chatgpt-is-still-more-art-than-science-259629
95
+ - **Strunk & White, "The Elements of Style"** — 간결성(Omit needless words)·능동태. · https://news.cornell.edu/stories/2009/03/omit-needless-words-elements-style-turns-50
96
+ - **TopResume "9 Cover Letter Cliches" / The Muse / Univ. of Michigan Career Center** — 빈 열정어·자기선언 금지, Show-don't-tell. · https://topresume.com/career-advice/cliches-cut-from-cover-letter
97
+ - **링커리어·하이잡·대웅 뉴스룸 STAR 기법 가이드** — 한국 채용: 두괄식("저는 ~입니다" 대표문장 정석), STAR, 추상 성격 나열 금지. · https://community.linkareer.com/employment_data/4464545
98
+ - **CareerMate AGENTS.md** — 프라임 디렉티브("두뇌는 당신, 저장은 CareerMate"), 사실·수치·고유명사 보존, get_application_context의 matched/missing_keywords.
99
+
100
+ ## 5. Phase B 힌트 (아키텍처로 연결)
101
+
102
+ - **MCP 도구 아이디어:**
103
+ - `get_writing_style_guide(doc_type, locale)` 확장 — 위 원칙·Do·Don't를 locale별(ko 우선, en 보조)로 반환. 기존 humanize.ts를 이 데이터의 1차 소스로 흡수.
104
+ - `check_human_writing(text, locale, sourceFacts?, maxChars?, jdKeywords?, voiceSample?)` 신설 — **LLM 없이 결정론**으로 violations 배열 + pass/fail 반환. R1~R6·R9~R12는 순수 JS 카운트/정규식/집합연산. **R7(fact-lock)·R10·두괄식 본질은 "휴리스틱 플래그"로 반환하고 최종 판정은 연결된 AI에게 위임**(한국어 NER·의미 판정 불가 인정).
105
+ - **데이터 형태 힌트:**
106
+ ```
107
+ styleGuide: { domain, locale, principles[], doList[], dontList[] }
108
+ lexicons: { // 버전드 JSON, 거버넌스 메타 필수
109
+ _meta: { version, sourceDate, calibratedOn, changelog[] },
110
+ slop_ko: [{term, replaceWith, regex?}], // 1차
111
+ aiOveruse_en: [{term, replaceWith, wordBoundary:true, contextWhitelist:[]}], // 영문 한정
112
+ hedging: [], emptyEnthusiasm: [], formatTells_ko: ['·','**','emoji']
113
+ }
114
+ rubric: [{ id, check, passBar, regexOrLexiconRef, locale, severity:'gate'|'soft'|'llm-flag', minSentences? }]
115
+ ```
116
+ - **입력:** `{ text, locale, sourceFacts?, maxChars?, jdKeywords?, voiceSample? }`
117
+ - **출력:** `{ score, gatePassed, violations:[{ruleId, severity, count, matches:[{text,offset}]}], factLock:{normalizedNumbers, unmatched[], note:'LLM-confirm'}, jobFit:{coverage, missing[]}, metrics:{emDash, midDot, sentenceLenStdev, evidencePerUnit, charCount, voiceDelta} }`
118
+ - **거버넌스(필수):** lexicon 변경은 (a) version/sourceDate 기록, (b) 한국어 false-positive 회귀 테스트셋 통과, (c) 합격 자소서 N건 + AI 슬롭 N건 골든셋에 대한 precision/recall 리포트, (d) 분기별 재캘리브레이션 트리거를 거친다. 기술 용어 화이트리스트(robust/foster/navigate)는 contextWhitelist로 관리.