@tienne/gestalt 0.72.8 → 0.73.0

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 (59) hide show
  1. package/CLAUDE.md +18 -3
  2. package/README.ko.md +5 -5
  3. package/README.md +5 -5
  4. package/dist/package.json +9 -1
  5. package/dist/plugin/role-agents/explainer/AGENT.md +71 -0
  6. package/dist/plugin/role-agents/explainer/references/audience.md +147 -0
  7. package/dist/plugin/skills/_shared/agent-delegation.md +1 -1
  8. package/dist/plugin/skills/_shared/proactive-routing.md +2 -0
  9. package/dist/plugin/skills/explain/SKILL.md +179 -0
  10. package/dist/src/cli/commands/explain-check.d.ts +11 -0
  11. package/dist/src/cli/commands/explain-check.d.ts.map +1 -0
  12. package/dist/src/cli/commands/explain-check.js +53 -0
  13. package/dist/src/cli/commands/explain-check.js.map +1 -0
  14. package/dist/src/cli/commands/explain-eval.d.ts +110 -0
  15. package/dist/src/cli/commands/explain-eval.d.ts.map +1 -0
  16. package/dist/src/cli/commands/explain-eval.js +272 -0
  17. package/dist/src/cli/commands/explain-eval.js.map +1 -0
  18. package/dist/src/cli/index.d.ts.map +1 -1
  19. package/dist/src/cli/index.js +26 -0
  20. package/dist/src/cli/index.js.map +1 -1
  21. package/dist/src/core/version.d.ts +45 -0
  22. package/dist/src/core/version.d.ts.map +1 -1
  23. package/dist/src/core/version.js +87 -2
  24. package/dist/src/core/version.js.map +1 -1
  25. package/dist/src/explain/audience.d.ts +85 -0
  26. package/dist/src/explain/audience.d.ts.map +1 -0
  27. package/dist/src/explain/audience.js +121 -0
  28. package/dist/src/explain/audience.js.map +1 -0
  29. package/dist/src/explain/check.d.ts +83 -0
  30. package/dist/src/explain/check.d.ts.map +1 -0
  31. package/dist/src/explain/check.js +506 -0
  32. package/dist/src/explain/check.js.map +1 -0
  33. package/dist/src/explain/grounding.d.ts +40 -0
  34. package/dist/src/explain/grounding.d.ts.map +1 -0
  35. package/dist/src/explain/grounding.js +114 -0
  36. package/dist/src/explain/grounding.js.map +1 -0
  37. package/dist/src/explain/index.d.ts +5 -0
  38. package/dist/src/explain/index.d.ts.map +1 -0
  39. package/dist/src/explain/index.js +5 -0
  40. package/dist/src/explain/index.js.map +1 -0
  41. package/dist/src/explain/terms.d.ts +71 -0
  42. package/dist/src/explain/terms.d.ts.map +1 -0
  43. package/dist/src/explain/terms.js +266 -0
  44. package/dist/src/explain/terms.js.map +1 -0
  45. package/dist/src/mcp/server.d.ts.map +1 -1
  46. package/dist/src/mcp/server.js +45 -21
  47. package/dist/src/mcp/server.js.map +1 -1
  48. package/dist/src/mcp/tools/status.d.ts.map +1 -1
  49. package/dist/src/mcp/tools/status.js +7 -2
  50. package/dist/src/mcp/tools/status.js.map +1 -1
  51. package/package.json +9 -1
  52. package/plugin/.codex-plugin/plugin.json +1 -1
  53. package/plugin/.mcp.json +1 -1
  54. package/plugin/mcp.json +1 -1
  55. package/plugin/role-agents/explainer/AGENT.md +71 -0
  56. package/plugin/role-agents/explainer/references/audience.md +147 -0
  57. package/plugin/skills/_shared/agent-delegation.md +1 -1
  58. package/plugin/skills/_shared/proactive-routing.md +2 -0
  59. package/plugin/skills/explain/SKILL.md +179 -0
@@ -1,5 +1,6 @@
1
1
  import { createRequire } from 'node:module';
2
2
  import { existsSync, readFileSync, writeFileSync } from 'node:fs';
3
+ import { join } from 'node:path';
3
4
  import { gestaltPath, ensureGestaltHome } from './home.js';
4
5
  const require = createRequire(import.meta.url);
5
6
  let cachedUpdateResult = null;
@@ -7,6 +8,44 @@ export function getVersion() {
7
8
  const pkg = require('../../package.json');
8
9
  return pkg.version;
9
10
  }
11
+ /**
12
+ * 이 세션이 실제로 로드한 플러그인 버전. 플러그인으로 안 떴으면 null이다.
13
+ *
14
+ * Claude Code가 플러그인 매니페스트로 MCP 서버를 띄우면 `CLAUDE_PLUGIN_ROOT`가 서버
15
+ * 프로세스까지 상속된다. 그 경로가 스킬과 에이전트를 읽어온 자리다.
16
+ *
17
+ * **서버 자기 버전(`getVersion`)과 어긋날 수 있다.** `mcp-serve.sh`는 전역 `gestalt`가
18
+ * 있으면 핀보다 그걸 먼저 쓰므로, 누가 `npm i -g`를 해두면 서버만 최신이고 스킬은
19
+ * 플러그인 캐시의 옛 버전이 된다. 그때 알려야 하는 쪽은 플러그인이다 — 사용자가 읽는
20
+ * 지시문이 거기서 오기 때문이다. 서버가 최신이어도 옛 스킬이 없는 도구를 부른다.
21
+ *
22
+ * 캐시 경로의 마지막 조각도 버전이지만(`.../gestalt/0.72.5`) 그건 Claude Code의 캐시
23
+ * 배치일 뿐이라 안 쓴다. 매니페스트를 읽는 쪽이 계약이다.
24
+ */
25
+ export function getPluginVersion() {
26
+ const root = process.env['CLAUDE_PLUGIN_ROOT'];
27
+ if (root === undefined || root === '')
28
+ return null;
29
+ try {
30
+ const raw = readFileSync(join(root, '.claude-plugin', 'plugin.json'), 'utf-8');
31
+ const manifest = JSON.parse(raw);
32
+ return typeof manifest.version === 'string' ? manifest.version : null;
33
+ }
34
+ catch {
35
+ return null;
36
+ }
37
+ }
38
+ /**
39
+ * 최신 여부를 잴 기준 버전. **플러그인이 있으면 플러그인이 이긴다.**
40
+ *
41
+ * 플러그인 없이 CLI로 부른 경우와 매니페스트를 못 읽은 경우에 서버 버전으로 떨어진다.
42
+ */
43
+ export function getSessionVersion() {
44
+ const plugin = getPluginVersion();
45
+ if (plugin !== null)
46
+ return { version: plugin, source: 'plugin' };
47
+ return { version: getVersion(), source: 'server' };
48
+ }
10
49
  export function compareSemver(a, b) {
11
50
  const partsA = a.replace(/^v/, '').split('.').map(Number);
12
51
  const partsB = b.replace(/^v/, '').split('.').map(Number);
@@ -33,11 +72,14 @@ function readCache() {
33
72
  const data = JSON.parse(raw);
34
73
  if (Date.now() - data.timestamp > CACHE_TTL_MS)
35
74
  return null;
36
- const currentVersion = getVersion();
75
+ // 캐시에는 npm latest만 담는다. 기준 버전은 매번 다시 읽는다 — 같은 머신에서도
76
+ // 세션마다 로드된 플러그인 버전이 달라서 캐시에 굳혀두면 남의 세션 값을 쓴다.
77
+ const { version: currentVersion, source } = getSessionVersion();
37
78
  return {
38
79
  currentVersion,
39
80
  latestVersion: data.latestVersion,
40
81
  updateAvailable: compareSemver(data.latestVersion, currentVersion) > 0,
82
+ source,
41
83
  };
42
84
  }
43
85
  catch {
@@ -68,13 +110,14 @@ export async function checkForUpdates() {
68
110
  if (!response.ok)
69
111
  return null;
70
112
  const data = (await response.json());
71
- const currentVersion = getVersion();
113
+ const { version: currentVersion, source } = getSessionVersion();
72
114
  const latestVersion = data.version;
73
115
  writeCache(latestVersion);
74
116
  const result = {
75
117
  currentVersion,
76
118
  latestVersion,
77
119
  updateAvailable: compareSemver(latestVersion, currentVersion) > 0,
120
+ source,
78
121
  };
79
122
  cachedUpdateResult = result;
80
123
  return result;
@@ -83,4 +126,46 @@ export async function checkForUpdates() {
83
126
  return null;
84
127
  }
85
128
  }
129
+ // ─── 세션에 한 번만 내보내는 알림 ────────────────────────────────────────────
130
+ /**
131
+ * 이 프로세스에서 배너를 이미 내보냈는지.
132
+ *
133
+ * MCP 서버는 세션 하나당 한 프로세스라 모듈 수준 플래그가 곧 "세션당 한 번"이 된다.
134
+ * 도구를 부를 때마다 붙이면 리뷰처럼 도구를 수십 번 부르는 스킬에서 같은 줄이
135
+ * 그만큼 쌓인다.
136
+ */
137
+ let bannerTaken = false;
138
+ /** 테스트에서 플래그를 되돌린다. 프로덕션 경로에서는 안 부른다 */
139
+ export function resetUpdateBanner() {
140
+ bannerTaken = false;
141
+ }
142
+ /**
143
+ * 아직 안 내보냈고 새 버전이 있으면 알림 한 줄을 돌려준다. 그 외에는 null이다.
144
+ *
145
+ * 여기서 네트워크를 안 탄다. `checkForUpdates()`가 서버 기동 때 걸어둔 결과만 읽으므로
146
+ * 도구 응답이 조회를 기다리는 일이 없다. 기동 직후 첫 호출이 조회보다 빠르면 그 판은
147
+ * 그냥 넘어가고 다음 도구 호출에서 뜬다.
148
+ */
149
+ export function takeUpdateBanner() {
150
+ if (bannerTaken)
151
+ return null;
152
+ const result = getCachedUpdateResult();
153
+ if (!result?.updateAvailable)
154
+ return null;
155
+ bannerTaken = true;
156
+ return formatUpdateBanner(result);
157
+ }
158
+ /**
159
+ * 알림 문구. 어디를 갱신해야 하는지가 `source`에 따라 갈린다.
160
+ *
161
+ * 플러그인이 뒤처진 경우에 `npm i -g`를 안내하면 안 된다. 그건 서버만 올리고 스킬은
162
+ * 그대로 두는 명령이라, 사용자가 시킨 대로 해도 같은 알림이 다음 세션에 또 뜬다.
163
+ */
164
+ export function formatUpdateBanner(result) {
165
+ const { currentVersion, latestVersion, source } = result;
166
+ const how = source === 'plugin'
167
+ ? '`/plugin install gestalt@gestalt` 로 갱신하고 세션을 다시 시작하세요.'
168
+ : '`gestalt update` 로 갱신하세요.';
169
+ return `[gestalt] 새 버전이 있어요 — ${currentVersion} → ${latestVersion}\n${how}`;
170
+ }
86
171
  //# sourceMappingURL=version.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"version.js","sourceRoot":"","sources":["../../../src/core/version.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"version.js","sourceRoot":"","sources":["../../../src/core/version.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,85 @@
1
+ /**
2
+ * 설명 대상 프리셋.
3
+ *
4
+ * 여섯 값이 용어 허용치와 문장 길이, 원문 핵심어를 얼마나 남겨야 하는지, 비유가 필요한지,
5
+ * 어미를 무엇으로 끝낼지를 한꺼번에 정한다. 사람이 읽는 기준은
6
+ * `plugin/role-agents/explainer/references/audience.md`가 말로 정하고 숫자는 이 파일이 갖는다.
7
+ * 두 곳에 같은 숫자를 적으면 갈라지므로 문서는 방향을, 코드는 값을 든다.
8
+ *
9
+ * 임계값이 프리셋마다 다른 이유는 설명이 잘될수록 원문에서 멀어지기 때문이다. 같은 잣대를
10
+ * 들이대면 `outsider`용 좋은 설명이 `peer` 기준으로는 내용을 버린 글이 된다.
11
+ */
12
+ export type Audience = 'nontech' | 'junior' | 'peer' | 'manager' | 'exec' | 'outsider';
13
+ export declare const AUDIENCES: readonly Audience[];
14
+ /**
15
+ * 대상을 안 밝히면 동료 개발자로 본다.
16
+ *
17
+ * 개발 레포 안에서 `outsider`를 기본으로 잡으면 옆자리 개발자에게 일상 비유를 늘어놓는
18
+ * 글이 나간다. 반대 방향 실수가 훨씬 싸다.
19
+ */
20
+ export declare const DEFAULT_AUDIENCE: Audience;
21
+ /** 원문에서 핵심어로 볼 상위 몇 개 */
22
+ export declare const CORE_TERM_COUNT = 5;
23
+ /** 비유가 필요한 정도. required 는 없으면 채택 금지, recommended 는 경고 */
24
+ export type AnalogyRule = 'required' | 'recommended' | 'off';
25
+ /** polite 는 해요체, formal 은 합니다체 */
26
+ export type Register = 'polite' | 'formal';
27
+ /**
28
+ * 상한을 재는 축은 warn 을 넘으면 경고이고 abort 를 넘으면 채택 금지다.
29
+ * 하한을 재는 축(coverage)은 방향이 반대라 warn 아래가 경고이고 abort 아래가 채택 금지다.
30
+ */
31
+ export interface Band {
32
+ warn: number;
33
+ abort: number;
34
+ }
35
+ /**
36
+ * coverage 를 안 재는 대상.
37
+ *
38
+ * audience.md 가 용어를 전면 금지한 대상에게 핵심어를 남기라고 요구하면 두 규칙이 정면으로
39
+ * 부딪힌다. 시킨 대로 쓰면 검사에 걸리고 안 걸리려면 룰북을 어겨야 하는 자리가 생긴다.
40
+ * 그 대상은 축을 끈다. 사실이 틀렸는지는 `--judge` 의 accuracy 가 보는데 그건 기본으로
41
+ * 안 켜지므로, 기본 실행에서 그 세 대상의 내용 정합을 판정하는 축은 없다.
42
+ */
43
+ export type CoverageRule = Band | 'off';
44
+ export interface AudiencePreset {
45
+ audience: Audience;
46
+ who: string;
47
+ /** 풀이 없이 남은 전문용어 밀도. 출현 수를 설명본 어절 수로 나눈 값 */
48
+ jargon: Band;
49
+ /** 평균 문장 길이. 글자 수로 센다 */
50
+ sentence: Band;
51
+ /** 원문 핵심어 중 다뤄야 하는 최소 비율. 용어를 금지한 대상은 'off' */
52
+ coverage: CoverageRule;
53
+ analogy: AnalogyRule;
54
+ register: Register;
55
+ }
56
+ /**
57
+ * 숫자를 고를 때 쓴 기준.
58
+ *
59
+ * 이 값들은 audience.md 의 프리셋 표에서 옮겨온 게 아니다. 그 표는 용어와 비유, 깊이를
60
+ * 말로 정하고 숫자는 여기서 처음 정해진다 — 두 곳에 같은 숫자를 적으면 갈라지므로
61
+ * 문서는 방향을, 코드는 값을 갖는다. 값을 바꿀 때 대조할 곳은 아래 근거지 문서가 아니다.
62
+ *
63
+ * **jargon** — nontech 과 exec 는 어절 200개에 풀이 없는 용어가 하나 나오면 경고(0.005)다.
64
+ * 그보다 잦으면 풀이를 빠뜨린 것이다. outsider 는 그보다 엄격해 하나만 나와도 바로
65
+ * 경고(warn 0)다 — 룰북이 그 대상에게는 우회할 수 없으면 그 얘기를 빼라고 적어서다.
66
+ * peer 는 반대로 거의 안 걸려야 한다 — 재보면 동료용 짧은 문장 하나에 용어 셋이 30%
67
+ * 근처라 그 위(0.35)에 둔다.
68
+ *
69
+ * **sentence** — 기준은 peer 의 70자다. 한글 산문에서 그쯤이면 한 번에 읽히는 끝이다.
70
+ * outsider 는 그 절반(35)이고 나머지는 사이에 둔다.
71
+ *
72
+ * **coverage** — 용어를 허용한 대상만 잰다. 핵심어를 다섯 개 잡으므로 0.6 은 셋, 0.8 은
73
+ * 넷이다. peer 는 넷을 요구하고 manager 는 절반이면 된다. 나머지 셋은 아래 CoverageRule
74
+ * 주석대로 축을 끈다.
75
+ */
76
+ export declare const PRESETS: Record<Audience, AudiencePreset>;
77
+ export declare function isAudience(value: string): value is Audience;
78
+ /**
79
+ * 값이 없으면 기본값, 모르는 값이면 undefined. 종료 코드는 부르는 쪽이 정한다.
80
+ *
81
+ * 빈 문자열도 안 준 것으로 본다. commander 가 `--audience` 를 값 없이 받으면 그 꼴로 온다.
82
+ */
83
+ export declare function parseAudience(value?: string): Audience | undefined;
84
+ export declare function presetOf(audience: Audience): AudiencePreset;
85
+ //# sourceMappingURL=audience.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audience.d.ts","sourceRoot":"","sources":["../../../src/explain/audience.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,MAAM,MAAM,QAAQ,GAAG,SAAS,GAAG,QAAQ,GAAG,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,UAAU,CAAC;AAEvF,eAAO,MAAM,SAAS,EAAE,SAAS,QAAQ,EAOxC,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,gBAAgB,EAAE,QAAiB,CAAC;AAEjD,yBAAyB;AACzB,eAAO,MAAM,eAAe,IAAI,CAAC;AAEjC,yDAAyD;AACzD,MAAM,MAAM,WAAW,GAAG,UAAU,GAAG,aAAa,GAAG,KAAK,CAAC;AAE7D,kCAAkC;AAClC,MAAM,MAAM,QAAQ,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAE3C;;;GAGG;AACH,MAAM,WAAW,IAAI;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;;;;;;GAOG;AACH,MAAM,MAAM,YAAY,GAAG,IAAI,GAAG,KAAK,CAAC;AAExC,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,QAAQ,CAAC;IACnB,GAAG,EAAE,MAAM,CAAC;IACZ,6CAA6C;IAC7C,MAAM,EAAE,IAAI,CAAC;IACb,yBAAyB;IACzB,QAAQ,EAAE,IAAI,CAAC;IACf,+CAA+C;IAC/C,QAAQ,EAAE,YAAY,CAAC;IACvB,OAAO,EAAE,WAAW,CAAC;IACrB,QAAQ,EAAE,QAAQ,CAAC;CACpB;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,eAAO,MAAM,OAAO,EAAE,MAAM,CAAC,QAAQ,EAAE,cAAc,CAuDpD,CAAC;AAEF,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,IAAI,QAAQ,CAE3D;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,QAAQ,GAAG,SAAS,CAGlE;AAED,wBAAgB,QAAQ,CAAC,QAAQ,EAAE,QAAQ,GAAG,cAAc,CAE3D"}
@@ -0,0 +1,121 @@
1
+ /**
2
+ * 설명 대상 프리셋.
3
+ *
4
+ * 여섯 값이 용어 허용치와 문장 길이, 원문 핵심어를 얼마나 남겨야 하는지, 비유가 필요한지,
5
+ * 어미를 무엇으로 끝낼지를 한꺼번에 정한다. 사람이 읽는 기준은
6
+ * `plugin/role-agents/explainer/references/audience.md`가 말로 정하고 숫자는 이 파일이 갖는다.
7
+ * 두 곳에 같은 숫자를 적으면 갈라지므로 문서는 방향을, 코드는 값을 든다.
8
+ *
9
+ * 임계값이 프리셋마다 다른 이유는 설명이 잘될수록 원문에서 멀어지기 때문이다. 같은 잣대를
10
+ * 들이대면 `outsider`용 좋은 설명이 `peer` 기준으로는 내용을 버린 글이 된다.
11
+ */
12
+ export const AUDIENCES = [
13
+ 'nontech',
14
+ 'junior',
15
+ 'peer',
16
+ 'manager',
17
+ 'exec',
18
+ 'outsider',
19
+ ];
20
+ /**
21
+ * 대상을 안 밝히면 동료 개발자로 본다.
22
+ *
23
+ * 개발 레포 안에서 `outsider`를 기본으로 잡으면 옆자리 개발자에게 일상 비유를 늘어놓는
24
+ * 글이 나간다. 반대 방향 실수가 훨씬 싸다.
25
+ */
26
+ export const DEFAULT_AUDIENCE = 'peer';
27
+ /** 원문에서 핵심어로 볼 상위 몇 개 */
28
+ export const CORE_TERM_COUNT = 5;
29
+ /**
30
+ * 숫자를 고를 때 쓴 기준.
31
+ *
32
+ * 이 값들은 audience.md 의 프리셋 표에서 옮겨온 게 아니다. 그 표는 용어와 비유, 깊이를
33
+ * 말로 정하고 숫자는 여기서 처음 정해진다 — 두 곳에 같은 숫자를 적으면 갈라지므로
34
+ * 문서는 방향을, 코드는 값을 갖는다. 값을 바꿀 때 대조할 곳은 아래 근거지 문서가 아니다.
35
+ *
36
+ * **jargon** — nontech 과 exec 는 어절 200개에 풀이 없는 용어가 하나 나오면 경고(0.005)다.
37
+ * 그보다 잦으면 풀이를 빠뜨린 것이다. outsider 는 그보다 엄격해 하나만 나와도 바로
38
+ * 경고(warn 0)다 — 룰북이 그 대상에게는 우회할 수 없으면 그 얘기를 빼라고 적어서다.
39
+ * peer 는 반대로 거의 안 걸려야 한다 — 재보면 동료용 짧은 문장 하나에 용어 셋이 30%
40
+ * 근처라 그 위(0.35)에 둔다.
41
+ *
42
+ * **sentence** — 기준은 peer 의 70자다. 한글 산문에서 그쯤이면 한 번에 읽히는 끝이다.
43
+ * outsider 는 그 절반(35)이고 나머지는 사이에 둔다.
44
+ *
45
+ * **coverage** — 용어를 허용한 대상만 잰다. 핵심어를 다섯 개 잡으므로 0.6 은 셋, 0.8 은
46
+ * 넷이다. peer 는 넷을 요구하고 manager 는 절반이면 된다. 나머지 셋은 아래 CoverageRule
47
+ * 주석대로 축을 끈다.
48
+ */
49
+ export const PRESETS = {
50
+ nontech: {
51
+ audience: 'nontech',
52
+ who: '기획, 디자인, 마케팅 동료',
53
+ jargon: { warn: 0.005, abort: 0.02 },
54
+ sentence: { warn: 45, abort: 60 },
55
+ coverage: 'off',
56
+ analogy: 'required',
57
+ register: 'polite',
58
+ },
59
+ junior: {
60
+ audience: 'junior',
61
+ who: '주니어 개발자',
62
+ jargon: { warn: 0.06, abort: 0.12 },
63
+ sentence: { warn: 60, abort: 80 },
64
+ coverage: { warn: 0.7, abort: 0.5 },
65
+ analogy: 'recommended',
66
+ register: 'polite',
67
+ },
68
+ peer: {
69
+ audience: 'peer',
70
+ who: '동료 개발자',
71
+ jargon: { warn: 0.35, abort: 0.5 },
72
+ sentence: { warn: 70, abort: 95 },
73
+ coverage: { warn: 0.8, abort: 0.6 },
74
+ analogy: 'off',
75
+ register: 'polite',
76
+ },
77
+ manager: {
78
+ audience: 'manager',
79
+ who: '관리자',
80
+ jargon: { warn: 0.02, abort: 0.05 },
81
+ sentence: { warn: 55, abort: 75 },
82
+ coverage: { warn: 0.5, abort: 0.3 },
83
+ analogy: 'off',
84
+ register: 'formal',
85
+ },
86
+ exec: {
87
+ audience: 'exec',
88
+ who: '경영진',
89
+ jargon: { warn: 0.005, abort: 0.02 },
90
+ sentence: { warn: 50, abort: 70 },
91
+ coverage: 'off',
92
+ analogy: 'off',
93
+ register: 'formal',
94
+ },
95
+ outsider: {
96
+ audience: 'outsider',
97
+ who: '사외 비전문가, 가족',
98
+ jargon: { warn: 0, abort: 0.01 },
99
+ sentence: { warn: 35, abort: 50 },
100
+ coverage: 'off',
101
+ analogy: 'required',
102
+ register: 'polite',
103
+ },
104
+ };
105
+ export function isAudience(value) {
106
+ return AUDIENCES.includes(value);
107
+ }
108
+ /**
109
+ * 값이 없으면 기본값, 모르는 값이면 undefined. 종료 코드는 부르는 쪽이 정한다.
110
+ *
111
+ * 빈 문자열도 안 준 것으로 본다. commander 가 `--audience` 를 값 없이 받으면 그 꼴로 온다.
112
+ */
113
+ export function parseAudience(value) {
114
+ if (value === undefined || value === '')
115
+ return DEFAULT_AUDIENCE;
116
+ return isAudience(value) ? value : undefined;
117
+ }
118
+ export function presetOf(audience) {
119
+ return PRESETS[audience];
120
+ }
121
+ //# sourceMappingURL=audience.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audience.js","sourceRoot":"","sources":["../../../src/explain/audience.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,83 @@
1
+ /**
2
+ * 설명이 그 대상에게 읽히는 글인지 코드가 판단하는 검사.
3
+ *
4
+ * humanize-check 와 판정 구조만 같고 재는 것은 반대다. 거기는 의미가 보존됐는지를 보고
5
+ * 원문을 절반 넘게 버리면 채택 금지다. 설명은 원문을 많이 버려야 성공이라 그 검사를 그대로
6
+ * 쓰면 잘된 설명일수록 막힌다. 그래서 축을 새로 잡았다 — 용어, 문장 길이, 핵심어 잔존,
7
+ * 비유, 어미, 사실 정확도.
8
+ *
9
+ * 여섯 중 다섯이 결정론이다. LLM 없이 돌고 같은 입력에 같은 점수가 나온다. 심판 모델은
10
+ * 사실이 틀렸는지 하나만 본다 — 그건 코드가 못 재는 자리라서다.
11
+ */
12
+ import { EXIT_CODE, MAX_ATTEMPTS, type Decision, type NextAction, type Verdict } from '../humanize/check.js';
13
+ import type { LLMAdapter } from '../llm/types.js';
14
+ import { type Audience } from './audience.js';
15
+ import { type Grounding } from './grounding.js';
16
+ export { EXIT_CODE, MAX_ATTEMPTS, type Decision, type NextAction, type Verdict };
17
+ export type ExplainAxis = 'jargon' | 'length' | 'grounding' | 'coverage' | 'analogy' | 'register' | 'accuracy';
18
+ /** 심판 모델 없이 도는 축. `--judge` 를 안 켜도 검사가 성립한다는 근거다 */
19
+ export declare const DETERMINISTIC_AXES: readonly ExplainAxis[];
20
+ export interface AxisResult {
21
+ axis: ExplainAxis;
22
+ verdict: Verdict;
23
+ detail: string;
24
+ evidence?: string[];
25
+ }
26
+ export interface ExplainMetrics {
27
+ words: number;
28
+ sentences: number;
29
+ avgSentenceLength: number;
30
+ /** 풀이 없이 남은 용어 출현 수를 어절 수로 나눈 값 */
31
+ jargonDensity: number;
32
+ unglossed: number;
33
+ glossed: number;
34
+ coverage: number;
35
+ coreTerms: string[];
36
+ coveredTerms: string[];
37
+ /** 원문에서 뽑은 전문용어 후보가 상한에서 잘렸나 */
38
+ termsTruncated: boolean;
39
+ grounding: Grounding;
40
+ analogyMarkers: string[];
41
+ register: RegisterStats;
42
+ }
43
+ export interface ExplainReport {
44
+ audience: Audience;
45
+ verdict: Verdict;
46
+ exitCode: number;
47
+ metrics: ExplainMetrics;
48
+ axes: AxisResult[];
49
+ }
50
+ export interface ExplainCheckOptions {
51
+ audience?: Audience;
52
+ }
53
+ export interface RegisterStats {
54
+ polite: number;
55
+ formal: number;
56
+ plain: number;
57
+ }
58
+ /**
59
+ * 어미를 갈래별로 센다.
60
+ *
61
+ * 인용줄을 뺀 산문을 따로 받는 건 남의 말투가 딸려오면 섞임으로 오판하기 때문이다.
62
+ * 그 산문을 만드는 일은 부르는 쪽이 한다 — runExplainCheck 가 같은 필터링을 두 번 태우지
63
+ * 않으려고 미리 만들어 넘긴다. 인자를 안 주면 여기서 만든다.
64
+ */
65
+ export declare function registerStats(text: string, prose?: string): RegisterStats;
66
+ export declare function runExplainCheck(source: string, explanation: string, options?: ExplainCheckOptions): ExplainReport;
67
+ /** 심판 축을 얹고 판정을 다시 낸다. 결정론 축은 그대로 둔다 */
68
+ export declare function withAxis(report: ExplainReport, axis: AxisResult): ExplainReport;
69
+ export interface JudgeInput {
70
+ source: string;
71
+ explanation: string;
72
+ audience: Audience;
73
+ }
74
+ /**
75
+ * 사실 정확도만 심판 모델에게 묻는다.
76
+ *
77
+ * 어댑터를 인자로 받아 이 파일이 설정을 안 읽게 막는다. 결정론 축은 파일만 있으면 돌아야
78
+ * 하는데 설정을 여기서 읽으면 그 조건이 깨진다.
79
+ */
80
+ export declare function judgeAccuracy(adapter: LLMAdapter, input: JudgeInput): Promise<AxisResult>;
81
+ export declare function decide(report: ExplainReport, attempt?: number, maxAttempts?: number): Decision;
82
+ export declare function formatExplainReport(report: ExplainReport, attempt?: number): string;
83
+ //# sourceMappingURL=check.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"check.d.ts","sourceRoot":"","sources":["../../../src/explain/check.ts"],"names":[],"mappings":"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"}