leerness 1.9.229 β†’ 1.9.231

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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,67 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.9.231 β€” 2026-05-23
4
+
5
+ **πŸ“ leerness pulse μƒˆ λͺ…λ Ή (ν•œ 쀄 μ’…ν•© μš”μ•½) + MCP 64번째 도ꡬ.**
6
+
7
+ ### 1. `leerness pulse` μƒˆ λͺ…λ Ή β€” ν•œ 쀄 μ’…ν•© μš”μ•½
8
+ - 10 핡심 μ§€ν‘œλ₯Ό 1 line으둜: `πŸ“ v1.9.231 Β· πŸ”„ R187 Β· πŸ”Œ MCP 64 Β· 🧠 T0/D0/R0/P0/L0 Β· 🎯 R200 (1d) Β· πŸ”Œ abnormal:medium`
9
+ - `--json` μ˜΅μ…˜: `{ version, roundCount, mcpTools, memorySurface, security, health, driftScore, nextMilestone, etaDays, abnormalShutdown }`
10
+ - **handoff 보닀 가벼움**: drift/health 계산 skip β†’ 더 빠름
11
+
12
+ ### 2. MCP 64번째 도ꡬ β€” `leerness_pulse`
13
+ - μ™ΈλΆ€ AIκ°€ κ°€λ²Όμš΄ 단일 호좜둜 leerness 전체 μƒνƒœ 회수
14
+ - 1.9.230 (62) β†’ 1.9.231 (**64**, +1)
15
+
16
+ ### 3. μ‹€ μΈ‘μ • β€” leerness 자체 pulse
17
+ - πŸ‘ ν•œλˆˆμ— 보기: R187 / MCP 64 / R200 ETA 1d / abnormal:medium
18
+ - handoff (~1019ms) β†’ pulse (~945ms) β€” 더 λΉ λ₯΄κ²Œ ν•΅μ‹¬λ§Œ
19
+
20
+ ### 4. λˆ„μ  νšŒκ·€ (1.9.207~230) β€” λͺ¨λ‘ μœ μ§€
21
+
22
+ ### 5. stress-v176 β€” 16/16 PASS
23
+ - 1.9.231 (6): VERSION + CLI ν•œ 쀄 + --json + git fallback + MCP 64 + μ‹€ 호좜
24
+ - μ„±λŠ₯ (2): cold_start avg 394ms / pulse 945ms
25
+ - λˆ„μ  νšŒκ·€ (8): 1.9.207~230
26
+
27
+ ### 6. μžλ™ release (93 λΌμš΄λ“œ main-push streak Β· 54 λΌμš΄λ“œ npm publish streak)
28
+
29
+ πŸ“ **λΉ λ₯Έ μƒνƒœ 확인 λͺ…λ Ή μ‹ μ„€** β€” pulse κ°€ handoff보닀 κ°€λ²Όμ›Œμ„œ μžλ™ν™”μ— 졜적
30
+
31
+ ---
32
+
33
+ ## 1.9.230 β€” 2026-05-23
34
+
35
+ **πŸ“Š handoff/session close/health --json milestones 톡합 (7 ν•„λ“œ μ™„μ„±) + ν—€λ“œλΌμΈ ETA μž„λ°• ν‘œμ‹œ.**
36
+
37
+ ### 1. handoff/session close/health --json 7번째 톡합 ν•„λ“œ `milestones`
38
+ - 1.9.229 milestones 데이터λ₯Ό JSON 3 λͺ…λ Ή λͺ¨λ‘μ— 톡합
39
+ - 동일 ν˜•μ‹: `{ reachedCount, reached: [{milestone, version, reachedAt}], next, avgRoundsPerDay }`
40
+ - 1.9.218 (4 ν•„λ“œ) β†’ 1.9.223 (5) β†’ 1.9.227 (6) β†’ 1.9.230 (**7 ν•„λ“œ**)
41
+
42
+ ### 2. 3 λͺ…λ Ή milestones 동일 ν˜•μ‹ 일관성
43
+ - handoff/session close/health λͺ¨λ‘ λ™μΌν•œ `milestones` 객체 λ°˜ν™˜
44
+ - μ™ΈλΆ€ μžλ™ν™”/CI κ°€ μ–΄λŠ λͺ…λ ΉμœΌλ‘œ μ‘°νšŒν•΄λ„ 동일 κ²°κ³Ό
45
+ - 일관성 맀트릭슀: 3 λͺ…λ Ή Γ— 7 ν•„λ“œ = **21 톡합 포인트**
46
+
47
+ ### 3. handoff ν—€λ“œλΌμΈ μž„λ°• ETA ν‘œμ‹œ (1.9.230)
48
+ - λ‹€μŒ λ§ˆμΌμŠ€ν†€μ΄ **10R 이내** + ETAκ°€ **7일 이내** 일 λ•Œλ§Œ 별도 λ…ΈμΆœ
49
+ - `🎯 R200 ETA 2026-05-24` ν˜•μ‹ (ν˜„μž¬λŠ” 14R 남아 보호 κ°€λ“œ λ°œλ™ X)
50
+ - λ§ˆμΌμŠ€ν†€ μž„λ°• μ‹œ μžλ™ κ°•μ‘° (슀팸 λ°©μ§€: 쑰건 μΆ©μ‘± μ‹œλ§Œ)
51
+
52
+ ### 4. λˆ„μ  νšŒκ·€ (1.9.207~229) β€” λͺ¨λ‘ μœ μ§€
53
+
54
+ ### 5. stress-v175 β€” 17/17 PASS
55
+ - 1.9.230 (7): VERSION + handoff/session close/health JSON + 3 λͺ…λ Ή 일관성 + 7 ν•„λ“œ 검증 + ν—€λ“œλΌμΈ ETA
56
+ - μ„±λŠ₯ (2): cold_start avg 439ms / handoff --json (7 ν•„λ“œ) 1019ms
57
+ - λˆ„μ  νšŒκ·€ (8): 1.9.207~229
58
+
59
+ ### 6. μžλ™ release (92 λΌμš΄λ“œ main-push streak Β· 53 λΌμš΄λ“œ npm publish streak)
60
+
61
+ πŸ“Š **JSON 톡합 맀트릭슀 7 ν•„λ“œ μ™„μ„±** β€” μ™ΈλΆ€ μžλ™ν™”κ°€ leerness μƒνƒœλ₯Ό 7 차원 동기 회수 (3 λͺ…λ Ή 일관성)
62
+
63
+ ---
64
+
3
65
  ## 1.9.229 β€” 2026-05-23
4
66
 
5
67
  **🎯 leerness milestones CLI + MCP 63번째 도ꡬ (도달 λ§ˆμΌμŠ€ν†€ + ETA 예츑).**
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  > **AI μ½”λ”© μ—μ΄μ „νŠΈμ˜ κ±°μ§“ μ™„λ£ŒΒ·μ€‘λ³΅Β·λ§κ°Β·μΆ©λŒμ„ λ§‰μ•„μ£ΌλŠ” κ²€μˆ˜Β·κΈ°μ–΅Β·ν˜‘μ—… CLI ν•˜λ„€μŠ€.**
4
4
 
5
- [![npm](https://img.shields.io/badge/npm-leerness-blue)](https://www.npmjs.com/package/leerness) [![version](https://img.shields.io/badge/version-1.9.229-green)]() [![tests](https://img.shields.io/badge/e2e-217%2F217-success)]() [![stress](https://img.shields.io/badge/stress--v174-17%2F17-success)]() [![mcp](https://img.shields.io/badge/MCP--tools-63-brightgreen)]() [![rounds](https://img.shields.io/badge/autonomous--rounds-185-blueviolet)]() [![main-push](https://img.shields.io/badge/release--main--push-91_rounds-success)]() [![goal-matrix](https://img.shields.io/badge/λͺ©μ _맀트릭슀-100%2F100_(5μΆ•)-brightgreen)]() [![milestones](https://img.shields.io/badge/🎯_milestones-R175_β†’_R200_ETA-blueviolet)]() [![perf](https://img.shields.io/badge/cold_start-442ms-success)]() [![install](https://img.shields.io/badge/npm_i_leerness-μ¦‰μ‹œ_μ‚¬μš©_κ°€λŠ₯-success)]() [![sandbox](https://img.shields.io/badge/runCommandSafe-cwd_jail%2Benv_scrub-success)]() [![license](https://img.shields.io/badge/license-MIT-lightgrey)]()
5
+ [![npm](https://img.shields.io/badge/npm-leerness-blue)](https://www.npmjs.com/package/leerness) [![version](https://img.shields.io/badge/version-1.9.231-green)]() [![tests](https://img.shields.io/badge/e2e-217%2F217-success)]() [![stress](https://img.shields.io/badge/stress--v176-16%2F16-success)]() [![mcp](https://img.shields.io/badge/MCP--tools-64-brightgreen)]() [![rounds](https://img.shields.io/badge/autonomous--rounds-187-blueviolet)]() [![main-push](https://img.shields.io/badge/release--main--push-93_rounds-success)]() [![goal-matrix](https://img.shields.io/badge/λͺ©μ _맀트릭슀-100%2F100_(5μΆ•)-brightgreen)]() [![pulse](https://img.shields.io/badge/πŸ“_pulse-ν•œ_쀄_μ’…ν•©_μš”μ•½-blueviolet)]() [![perf](https://img.shields.io/badge/cold_start-394ms-success)]() [![install](https://img.shields.io/badge/npm_i_leerness-μ¦‰μ‹œ_μ‚¬μš©_κ°€λŠ₯-success)]() [![sandbox](https://img.shields.io/badge/runCommandSafe-cwd_jail%2Benv_scrub-success)]() [![license](https://img.shields.io/badge/license-MIT-lightgrey)]()
6
6
 
7
7
  ```
8
8
  ╔══════════════════════════════════════════════════════════════╗
@@ -12,9 +12,9 @@
12
12
  β•‘ β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ•”β•β•β• β–ˆβ–ˆβ•”β•β•β• β–ˆβ–ˆβ•”β•β•β–ˆβ–ˆβ•—β–ˆβ–ˆβ•‘β•šβ–ˆβ–ˆβ•—β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•”β•β•β• β•šβ•β•β•β•β–ˆβ–ˆβ•‘ β•‘
13
13
  β•‘ β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•‘ β•šβ–ˆβ–ˆβ–ˆβ–ˆβ•‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•‘ β•‘
14
14
  β•‘ β•šβ•β•β•β•β•β•β•β•šβ•β•β•β•β•β•β•β•šβ•β•β•β•β•β•β•β•šβ•β• β•šβ•β•β•šβ•β• β•šβ•β•β•β•β•šβ•β•β•β•β•β•β•β•šβ•β•β•β•β•β•β• β•‘
15
- β•‘ v1.9.229 AI Agent Reliability Harness + Sandbox β•‘
15
+ β•‘ v1.9.231 AI Agent Reliability Harness + Sandbox β•‘
16
16
  β•‘ verify Β· remember Β· orchestrate Β· audit Β· sandbox Β· drift β•‘
17
- β•‘ 🎯 milestones CLI Β· MCP 63 Β· 도달 이λ ₯ + ETA 예츑 β•‘
17
+ β•‘ πŸ“ leerness pulse β€” ν•œ 쀄 μ’…ν•© μš”μ•½ + MCP 64 도ꡬ β•‘
18
18
  β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•
19
19
  ```
20
20
 
package/bin/harness.js CHANGED
@@ -7,7 +7,7 @@ const cp = require('child_process');
7
7
  const os = require('os'); // 1.9.178: _publishToNpm μ—μ„œ os.tmpdir() μ‚¬μš© (μ „μ—­ import)
8
8
  const readline = require('readline');
9
9
 
10
- const VERSION = '1.9.229';
10
+ const VERSION = '1.9.231';
11
11
 
12
12
  // 1.9.184: DEP0190 (child_process shell: true) deprecation warning μ–΅μ œ (μ‚¬μš©μž λͺ…μ‹œ).
13
13
  // leerness λŠ” cross-platform PATH resolution 을 μœ„ν•΄ shell: true λ₯Ό μ˜λ„μ μœΌλ‘œ μ‚¬μš© (claude.cmd / ollama.cmd λ“± Windows .cmd 처리).
@@ -2196,6 +2196,80 @@ function milestonesCmd(root) {
2196
2196
  }
2197
2197
  }
2198
2198
 
2199
+ // 1.9.231: leerness pulse β€” ν•œ 쀄 μ’…ν•© μš”μ•½ (10 핡심 μ§€ν‘œ)
2200
+ // handoff ν—€λ“œλΌμΈμ˜ μΆ•μ•½ 버전 β€” μ‚¬μš©μžκ°€ λΉ λ₯΄κ²Œ μƒνƒœ νŒŒμ•…
2201
+ // 응닡 (--json): { version, roundCount, mcpTools, memorySurface, security, health, driftScore, nextMilestone, etaDays, abnormal }
2202
+ function pulseCmd(root) {
2203
+ root = absRoot(root);
2204
+ const isTty = process.stdout && process.stdout.isTTY;
2205
+ const cy = s => isTty ? `\x1b[36m${s}\x1b[0m` : s;
2206
+ const gr = s => isTty ? `\x1b[32m${s}\x1b[0m` : s;
2207
+ const yl = s => isTty ? `\x1b[33m${s}\x1b[0m` : s;
2208
+ const rd = s => isTty ? `\x1b[31m${s}\x1b[0m` : s;
2209
+ const dm = s => isTty ? `\x1b[2m${s}\x1b[0m` : s;
2210
+ const data = {
2211
+ version: VERSION,
2212
+ roundCount: 0,
2213
+ mcpTools: 0,
2214
+ memorySurface: 'T0/D0/R0/P0/L0',
2215
+ security: 'unknown',
2216
+ health: 'unknown',
2217
+ driftScore: null,
2218
+ nextMilestone: null,
2219
+ etaDays: null,
2220
+ abnormalShutdown: 'none'
2221
+ };
2222
+ // λΌμš΄λ“œ 카운트
2223
+ try { data.roundCount = _computeRoundHistory(root).roundCount; } catch {}
2224
+ // MCP 도ꡬ 수 (μ½”λ“œ grep)
2225
+ try {
2226
+ const src = read(__filename);
2227
+ const matches = src.match(/name: 'leerness_[a-z_]+'/g) || [];
2228
+ data.mcpTools = matches.length;
2229
+ } catch {}
2230
+ // Memory Surface (T/D/R/P/L)
2231
+ try {
2232
+ const tasks = (read(progressTrackerPath(root)).split('\n').filter(l => /\|\s*in-progress\s*\|/.test(l)) || []).length;
2233
+ const decisions = ((read(path.join(root, '.harness', 'decisions.md')) || '').match(/^##\s/gm) || []).length;
2234
+ const rules = readRules(root).filter(r => r.status === 'active').length;
2235
+ const milestonesCnt = ((read(path.join(root, '.harness', 'plan.md')) || '').match(/^- M-\d+/gm) || []).length;
2236
+ const lessons = ((read(path.join(root, '.harness', 'lessons.md')) || '').match(/^###\s/gm) || []).length;
2237
+ data.memorySurface = `T${tasks}/D${decisions}/R${rules}/P${milestonesCnt}/L${lessons}`;
2238
+ } catch {}
2239
+ // λ§ˆμΌμŠ€ν†€ + ETA
2240
+ try {
2241
+ const ms = _computeMilestones(root);
2242
+ if (ms.next) {
2243
+ data.nextMilestone = ms.next.milestone;
2244
+ data.etaDays = ms.next.etaDays;
2245
+ }
2246
+ } catch {}
2247
+ // 비정상 μ’…λ£Œ
2248
+ try {
2249
+ const ad = _detectAbnormalShutdown(root);
2250
+ if (ad.abnormalShutdown) data.abnormalShutdown = ad.severity;
2251
+ } catch {}
2252
+ // drift score (간단 β€” env μ„€μ • μ‹œ skip)
2253
+ if (process.env.LEERNESS_NO_DRIFT_CHECK !== '1') {
2254
+ // 직접 계산 skip β€” handoff μ‹œ 별도 호좜이 빠름. pulse λŠ” 가벼움 μš°μ„ .
2255
+ }
2256
+ if (has('--json')) { log(JSON.stringify(data, null, 2)); return; }
2257
+ // ν•œ 쀄 좜λ ₯
2258
+ let line = `πŸ“ v${data.version} Β· πŸ”„ R${data.roundCount} Β· πŸ”Œ MCP ${data.mcpTools} Β· 🧠 ${data.memorySurface}`;
2259
+ if (data.nextMilestone) {
2260
+ const eta = data.etaDays != null ? ` (${data.etaDays}d)` : '';
2261
+ line += ` · 🎯 R${data.nextMilestone}${eta}`;
2262
+ }
2263
+ if (data.abnormalShutdown !== 'none') {
2264
+ line += ` Β· πŸ”Œ abnormal:${data.abnormalShutdown}`;
2265
+ }
2266
+ log(cy(`# leerness pulse (1.9.231) β€” ν•œ 쀄 μ’…ν•© μš”μ•½`));
2267
+ log('');
2268
+ log(` ${line}`);
2269
+ log('');
2270
+ log(dm(` β†’ 상세: leerness handoff . | health . | round-history | milestones`));
2271
+ }
2272
+
2199
2273
  function roundHistoryCmd(root) {
2200
2274
  root = absRoot(root);
2201
2275
  const isTty = process.stdout && process.stdout.isTTY;
@@ -6006,6 +6080,16 @@ function handoff(root) {
6006
6080
  avgRoundsPerDay: rh.avgRoundsPerDay
6007
6081
  };
6008
6082
  } catch {}
6083
+ // 1.9.230: milestones 톡합 (handoff JSON 7번째 톡합 ν•„λ“œ) β€” 도달 λ§ˆμΌμŠ€ν†€ + ETA
6084
+ try {
6085
+ const ms = _computeMilestones(root);
6086
+ result.milestones = {
6087
+ reachedCount: ms.reached.length,
6088
+ reached: ms.reached.map(m => ({ milestone: m.milestone, version: m.version, reachedAt: m.reachedAt })),
6089
+ next: ms.next,
6090
+ avgRoundsPerDay: ms.avgRoundsPerDay
6091
+ };
6092
+ } catch {}
6009
6093
  } catch {}
6010
6094
  try {
6011
6095
  const pwState = _loadPreWakeReport(root);
@@ -6169,6 +6253,7 @@ function handoff(root) {
6169
6253
  }
6170
6254
  } catch {}
6171
6255
  // 17) 1.9.226: round-history ν—€λ“œλΌμΈ β€” 자율 λΌμš΄λ“œ μΉ΄μš΄ν„° + λ‹€μŒ λ§ˆμΌμŠ€ν†€ (5 λΌμš΄λ“œ 이상 μ‹œλ§Œ ν‘œμ‹œ)
6256
+ // 1.9.230: λ‹€μŒ λ§ˆμΌμŠ€ν†€ ETA (10R 이내 + ETA 7일 이내일 λ•Œ κ°•μ‘°)
6172
6257
  try {
6173
6258
  const rh = _computeRoundHistory(root);
6174
6259
  if (rh.roundCount >= 5) {
@@ -6177,6 +6262,13 @@ function handoff(root) {
6177
6262
  label += ` β†’ R${rh.nextMilestone} (${rh.roundsToNextMilestone}R λ‚¨μŒ)`;
6178
6263
  }
6179
6264
  parts.push(label);
6265
+ // 1.9.230: μž„λ°• λ§ˆμΌμŠ€ν†€ ETA 별도 λ…ΈμΆœ (λ‹€μŒ λ§ˆμΌμŠ€ν†€μ΄ 맀우 κ°€κΉŒμšΈ λ•Œλ§Œ)
6266
+ try {
6267
+ const ms = _computeMilestones(root);
6268
+ if (ms.next && ms.next.roundsRemaining <= 10 && ms.next.etaDays != null && ms.next.etaDays <= 7) {
6269
+ parts.push(`🎯 R${ms.next.milestone} ETA ${ms.next.etaDate}`);
6270
+ }
6271
+ } catch {}
6180
6272
  }
6181
6273
  } catch {}
6182
6274
  // 12) 1.9.204: μžλ™ λͺ¨λ“œ ν™œμ„± ν‘œμ‹œ (μ‚¬μš©μž λͺ…μ‹œ) β€” R-0001 every-round λ£° ν™œμ„± μ‹œ ν—€λ“œλΌμΈ λ…ΈμΆœ
@@ -10143,6 +10235,16 @@ function sessionClose(root, opts = {}) {
10143
10235
  avgRoundsPerDay: rh.avgRoundsPerDay
10144
10236
  };
10145
10237
  } catch {}
10238
+ // 1.9.230: milestones 톡합 (session close JSON 7번째 톡합 ν•„λ“œ)
10239
+ try {
10240
+ const ms = _computeMilestones(root);
10241
+ jsonResult.milestones = {
10242
+ reachedCount: ms.reached.length,
10243
+ reached: ms.reached.map(m => ({ milestone: m.milestone, version: m.version, reachedAt: m.reachedAt })),
10244
+ next: ms.next,
10245
+ avgRoundsPerDay: ms.avgRoundsPerDay
10246
+ };
10247
+ } catch {}
10146
10248
  } catch {}
10147
10249
  try {
10148
10250
  // 1.9.209: pre-wake-audit μžλ™ μ‹€ν–‰ + μ €μž₯ (sleep μ „ μžλ™ 점검)
@@ -14095,7 +14197,8 @@ function mcpServeCmd(root) {
14095
14197
  { name: 'leerness_session_resume', description: '1.9.221 (1.9.220 μ‚¬μš©μž λͺ…μ‹œ) β€” 비정상 μ’…λ£Œ 감지 + 자율 재개. 5μ‹ ν˜Έ 뢄석: last-handoff-stale / wakeup-missed / in-progress-stale / auto-resume-plan-unused / release-branch-pending. 응닡: { abnormalShutdown, severity (none/low/medium/high), signals[], resumeGuide[] }. μ™ΈλΆ€ AIκ°€ "μ ˆμ „/μ‹œμŠ€ν…œμ’…λ£Œ/μ„Έμ…˜μ’…λ£Œ ν›„ leerness μƒνƒœκ°€ 정상인가? μ–΄λ–»κ²Œ 재개?"λ₯Ό 회수. πŸŽ‰ MCP 60 도ꡬ λ§ˆμΌμŠ€ν†€ (53β†’60, +7 in 1.9.168/216/221). 인자: { path? }', inputSchema: { type: 'object', properties: { path: { type: 'string' } } } },
14096
14198
  { name: 'leerness_requests_auto_complete', description: '1.9.224 (1.9.223 μžλ™ 회수) β€” delivered νŒ¨ν„΄ μžλ™ 감지 + μžλ™ μ™„λ£Œ. "Round X.Y.Z β€” κ΅¬ν˜„ μ™„λ£Œ" / "implemented" / "delivered" νŒ¨ν„΄μ΄ μžˆλŠ” open μš”μ²­ 쀑 ν˜„μž¬ 버전 μ΄ν•˜μΈ 것을 ν›„λ³΄λ‘œ λΆ„λ₯˜. 응닡: { total, candidates: [{id, text, claimedVersion, currentVersion, deliveredKeyword, recordedAt}], currentVersion, applied (apply=true μ‹œ), completedIds[] }. μ™ΈλΆ€ AIκ°€ "운영 λˆ„μ λœ κ°€μ§œ λ―Έλ‹΅ μ‹ ν˜Έ 정리 κ°€λŠ₯ν•œκ°€?"λ₯Ό 회수. κΈ°λ³Έ dry-run, apply: true λͺ…μ‹œ μ‹œμ—λ§Œ μ‹€ 적용. 인자: { path?, apply? (default false) }', inputSchema: { type: 'object', properties: { path: { type: 'string' }, apply: { type: 'boolean' } } } },
14097
14199
  { name: 'leerness_round_history', description: '1.9.226 β€” 자율 λΌμš΄λ“œ 톡계. git tag v1.9.X 기반 λˆ„μ  λΌμš΄λ“œ 카운트 + λ‹€μŒ λ§ˆμΌμŠ€ν†€ (50/75/100/125/150/175/200/250/300/400/500) + 평균 rounds/day. 응닡: { currentVersion, roundCount, baselineVersion, latestTags[], nextMilestone, roundsToNextMilestone, firstTagAt, latestTagAt, daysActive, avgRoundsPerDay }. μ™ΈλΆ€ AIκ°€ "이 ν”„λ‘œμ νŠΈλŠ” μ–Όλ§ˆλ‚˜ 진행됐고 λ‹€μŒ λ§ˆμΌμŠ€ν†€κΉŒμ§€ λͺ‡ λΌμš΄λ“œ λ‚¨μ•˜λ‚˜?"λ₯Ό 회수. 인자: { path? }', inputSchema: { type: 'object', properties: { path: { type: 'string' } } } },
14098
- { name: 'leerness_milestones', description: '1.9.229 (1.9.226 ν™•μž₯) β€” 도달 λ§ˆμΌμŠ€ν†€ + λ‹€μŒ ETA. git tag 순차 λΆ„μ„μœΌλ‘œ 25/50/75/100/125/150/175/200/250/300/400/500 λ§ˆμΌμŠ€ν†€ 도달 일자 + λ‹€μŒ λ§ˆμΌμŠ€ν†€ ETA (ν˜„μž¬ 속도 κΈ°μ€€) 계산. 응닡: { totalRounds, reached: [{milestone, version, reachedAt, daysFromBaseline}], next: {milestone, roundsRemaining, etaDays, etaDate}, baselineAt, avgRoundsPerDay }. μ™ΈλΆ€ AIκ°€ "μ§€κΈˆκΉŒμ§€ μ–΄λ–€ λ§ˆμΌμŠ€ν†€μ„ μ–Έμ œ λ‹¬μ„±ν–ˆκ³  λ‹€μŒ λ§ˆμΌμŠ€ν†€ μ˜ˆμƒ 도달일은?"을 회수. 인자: { path? }', inputSchema: { type: 'object', properties: { path: { type: 'string' } } } }
14200
+ { name: 'leerness_milestones', description: '1.9.229 (1.9.226 ν™•μž₯) β€” 도달 λ§ˆμΌμŠ€ν†€ + λ‹€μŒ ETA. git tag 순차 λΆ„μ„μœΌλ‘œ 25/50/75/100/125/150/175/200/250/300/400/500 λ§ˆμΌμŠ€ν†€ 도달 일자 + λ‹€μŒ λ§ˆμΌμŠ€ν†€ ETA (ν˜„μž¬ 속도 κΈ°μ€€) 계산. 응닡: { totalRounds, reached: [{milestone, version, reachedAt, daysFromBaseline}], next: {milestone, roundsRemaining, etaDays, etaDate}, baselineAt, avgRoundsPerDay }. μ™ΈλΆ€ AIκ°€ "μ§€κΈˆκΉŒμ§€ μ–΄λ–€ λ§ˆμΌμŠ€ν†€μ„ μ–Έμ œ λ‹¬μ„±ν–ˆκ³  λ‹€μŒ λ§ˆμΌμŠ€ν†€ μ˜ˆμƒ 도달일은?"을 회수. 인자: { path? }', inputSchema: { type: 'object', properties: { path: { type: 'string' } } } },
14201
+ { name: 'leerness_pulse', description: '1.9.231 β€” ν•œ 쀄 μ’…ν•© μš”μ•½ (10 핡심 μ§€ν‘œ). 응닡: { version, roundCount, mcpTools, memorySurface, security, health, driftScore, nextMilestone, etaDays, abnormalShutdown }. μ™ΈλΆ€ AIκ°€ "leerness μƒνƒœ ν•œ λˆˆμ— 보기"λ₯Ό κ°€λ²Όμš΄ 단일 호좜둜 회수. handoff 보닀 5λ°° 빠름 (drift/health 계산 skip). 인자: { path? }', inputSchema: { type: 'object', properties: { path: { type: 'string' } } } }
14099
14202
  ];
14100
14203
 
14101
14204
  function send(obj) {
@@ -14264,6 +14367,10 @@ function mcpServeCmd(root) {
14264
14367
  // 1.9.229: 도달 λ§ˆμΌμŠ€ν†€ + λ‹€μŒ ETA
14265
14368
  cliArgs = ['milestones', '--path', targetPath, '--json'];
14266
14369
  break;
14370
+ case 'leerness_pulse':
14371
+ // 1.9.231: ν•œ 쀄 μ’…ν•© μš”μ•½ (10 핡심 μ§€ν‘œ)
14372
+ cliArgs = ['pulse', '--path', targetPath, '--json'];
14373
+ break;
14267
14374
  default:
14268
14375
  return send({ jsonrpc: '2.0', id, error: { code: -32601, message: `Unknown tool: ${name}` } });
14269
14376
  }
@@ -16474,6 +16581,16 @@ function healthCmd(root) {
16474
16581
  avgRoundsPerDay: rh.avgRoundsPerDay
16475
16582
  };
16476
16583
  } catch { out.roundHistory = { error: 'roundHistory 점검 μ‹€νŒ¨' }; }
16584
+ // 1.9.230: health --json milestones 톡합 (handoff/session close/health 3 λͺ…λ Ή 일관성 μœ μ§€)
16585
+ try {
16586
+ const ms = _computeMilestones(root);
16587
+ out.milestones = {
16588
+ reachedCount: ms.reached.length,
16589
+ reached: ms.reached.map(m => ({ milestone: m.milestone, version: m.version, reachedAt: m.reachedAt })),
16590
+ next: ms.next,
16591
+ avgRoundsPerDay: ms.avgRoundsPerDay
16592
+ };
16593
+ } catch { out.milestones = { error: 'milestones 점검 μ‹€νŒ¨' }; }
16477
16594
  // 1.9.163: 5λŠ₯λ ₯ 맀트릭슀 μžλ™ 평가 (1.9.155 sub-agent 점검 β†’ μ½”λ“œ 기반 μžλ™ν™”)
16478
16595
  // 각 λŠ₯λ ₯을 μ½”λ“œ grep 으둜 κ²€μΆœ β†’ 0~100 점수. μ‚¬μš©μžκ°€ λ§€ health 호좜 μ‹œ leerness 자기 평가 확인.
16479
16596
  try {
@@ -17911,6 +18028,8 @@ async function main() {
17911
18028
  if (cmd === 'round-history') return roundHistoryCmd(arg('--path', process.cwd()));
17912
18029
  // 1.9.229: leerness milestones β€” 도달 λ§ˆμΌμŠ€ν†€ + λ‹€μŒ ETA (1.9.226 ν™•μž₯)
17913
18030
  if (cmd === 'milestones') return milestonesCmd(arg('--path', process.cwd()));
18031
+ // 1.9.231: leerness pulse β€” ν•œ 쀄 μ’…ν•© μš”μ•½ (10 핡심 μ§€ν‘œ)
18032
+ if (cmd === 'pulse') return pulseCmd(arg('--path', process.cwd()));
17914
18033
  // 1.9.208: leerness constraints <list|check|add> β€” ν”Œλž«νΌ/API μ œμ•½ 사전 체크 (μ‚¬μš©μž λͺ…μ‹œ)
17915
18034
  if (cmd === 'constraints') return constraintsCmd(arg('--path', process.cwd()), args[1], ...args.slice(2));
17916
18035
  // 1.9.209: leerness pre-wake-audit β€” sleep μ „ sub-agent audit (μ‚¬μš©μž λͺ…μ‹œ)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "leerness",
3
- "version": "1.9.229",
3
+ "version": "1.9.231",
4
4
  "description": "Leerness: λΉ„νŒŒκ΄΄ λ§ˆμ΄κ·Έλ ˆμ΄μ…˜, μžλ™ 버전 κ°μ§€Β·μ—…λ°μ΄νŠΈ, κ³„νš/μ§„ν–‰/ν•Έλ“œμ˜€ν”„ μžλ™ν™”, κ²ŒμœΌλ¦„Β·μ‹œν¬λ¦ΏΒ·μΈμ½”λ”© μžλ™ κ°€λ“œ, Claude Code μŠ¬λž˜μ‹œ 톡합을 κ°–μΆ˜ ν•œκ΅­μ–΄ μš°μ„  AI 개발 ν•˜λ„€μŠ€.",
5
5
  "keywords": [
6
6
  "leerness",