leerness 1.9.225 β†’ 1.9.227

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,83 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.9.227 β€” 2026-05-23
4
+
5
+ **πŸ“Š handoff/session close --json roundHistory 톡합 (6 ν•„λ“œ μ™„μ„±) + CLAUDE/AGENTS drift 차단.**
6
+
7
+ ### 1. handoff --json 6번째 톡합 ν•„λ“œ `roundHistory`
8
+ - `{ roundCount, baselineVersion, nextMilestone, roundsToNextMilestone, daysActive, avgRoundsPerDay }`
9
+ - μ™ΈλΆ€ CI/λͺ¨λ‹ˆν„°λ§μ΄ λΌμš΄λ“œ 진행도 + λ‹€μŒ λ§ˆμΌμŠ€ν†€ 직접 회수
10
+ - 1.9.218 (4 ν•„λ“œ) β†’ 1.9.223 (5 ν•„λ“œ) β†’ 1.9.227 (**6 ν•„λ“œ μ™„μ„±**)
11
+
12
+ ### 2. session close --json 6번째 톡합 ν•„λ“œ `roundHistory`
13
+ - 마감 μ‹œ 진행도 톡계 동기 λ…ΈμΆœ
14
+ - handoff/session close JSON 동일 νŒ¨ν„΄ μœ μ§€
15
+
16
+ ### 3. CLAUDE.md / AGENTS.md drift 차단 κ°±μ‹ 
17
+ - 1.9.222~227 6 λΌμš΄λ“œ λˆ„μ  톡합 (이전 κ°±μ‹ : 1.9.214)
18
+ - μ‹ κ·œ μ„Ήμ…˜: "μ‚¬μš©μž μš”μ²­ μžλ™ μ™„λ£Œ μ‹œμŠ€ν…œ (1.9.223~225)" + "λΌμš΄λ“œ 진행도 κ°€μ‹œν™” (1.9.226~227)"
19
+ - μƒˆ λ©”νƒ€νŒŒμΌ (last update: 1.9.214 β†’ 1.9.227, 6 λΌμš΄λ“œ λˆ„μ )
20
+
21
+ ### 4. 6 톡합 ν•„λ“œ 맀트릭슀 μ™„μ„± (handoff/session close --json 일관성)
22
+ - userRequestsAudit (1.9.207/218)
23
+ - preWakeAudit (1.9.209/218)
24
+ - idempotencyAudit (1.9.212/218)
25
+ - abnormalShutdown (1.9.220/221)
26
+ - deliveredRequests (1.9.223)
27
+ - **roundHistory** (1.9.226/227) ⭐
28
+
29
+ ### 5. λˆ„μ  νšŒκ·€ (1.9.207~226) β€” λͺ¨λ‘ μœ μ§€
30
+
31
+ ### 6. stress-v172 β€” 17/17 PASS
32
+ - 1.9.227 (7): VERSION + handoff JSON + session close JSON + 6 ν•„λ“œ 검증 (handoff) + 6 ν•„λ“œ 검증 (session close) + CLAUDE λˆ„μ  + AGENTS λˆ„μ 
33
+ - μ„±λŠ₯ (2): cold_start avg 400ms / handoff --json 641ms
34
+ - λˆ„μ  νšŒκ·€ (8): 1.9.207~226
35
+
36
+ ### 7. μžλ™ release (89 λΌμš΄λ“œ main-push streak Β· 50 λΌμš΄λ“œ npm publish streak πŸŽ‰)
37
+
38
+ πŸ“Š **JSON 톡합 맀트릭슀 μ™„μ„±** β€” μ™ΈλΆ€ μžλ™ν™”/CI κ°€ leerness μƒνƒœ 6 차원 동기 회수
39
+
40
+ πŸŽ‰ **50 λΌμš΄λ“œ npm publish streak 달성**
41
+
42
+ ---
43
+
44
+ ## 1.9.226 β€” 2026-05-23
45
+
46
+ **πŸ”„ round-history CLI + handoff ν—€λ“œλΌμΈ λΌμš΄λ“œ μΉ΄μš΄ν„° + MCP 62번째 도ꡬ.**
47
+
48
+ ### 1. `leerness round-history` μƒˆ λͺ…λ Ή β€” 자율 λΌμš΄λ“œ 톡계
49
+ - git tag `v1.9.X` 기반 λˆ„μ  λΌμš΄λ“œ 카운트 (graceful fallback: git μ—†μœΌλ©΄ 0)
50
+ - 응닡: `{ currentVersion, roundCount, baselineVersion, latestTags[], nextMilestone, roundsToNextMilestone, firstTagAt, latestTagAt, daysActive, avgRoundsPerDay }`
51
+ - λ§ˆμΌμŠ€ν†€ μžλ™ 감지: 50/75/100/125/150/175/200/250/300/400/500
52
+ - `--json` μ˜΅μ…˜ (μ™ΈλΆ€ μžλ™ν™”)
53
+
54
+ ### 2. handoff ν—€λ“œλΌμΈ 17번째 μš”μ†Œ
55
+ - 5 λΌμš΄λ“œ 이상 λˆ„μ  μ‹œ `πŸ”„ R<N>` μžλ™ λ…ΈμΆœ
56
+ - λ‹€μŒ λ§ˆμΌμŠ€ν†€μ΄ 20 λΌμš΄λ“œ 이내일 λ•Œ: `πŸ”„ R182 β†’ R200 (18R λ‚¨μŒ)` κ°•μ‘°
57
+ - 자율 λͺ¨λ“œ 진행도 ν•œλˆˆμ—
58
+
59
+ ### 3. MCP 62번째 도ꡬ β€” `leerness_round_history`
60
+ - μ™ΈλΆ€ AIκ°€ "이 ν”„λ‘œμ νŠΈλŠ” μ–Όλ§ˆλ‚˜ 진행됐고 λ‹€μŒ λ§ˆμΌμŠ€ν†€κΉŒμ§€ λͺ‡ λΌμš΄λ“œ λ‚¨μ•˜λ‚˜?"λ₯Ό 회수
61
+ - MCP 61 β†’ 62 (+1)
62
+
63
+ ### 4. μ‹€ μΈ‘μ • (leerness 자체 ν”„λ‘œμ νŠΈ)
64
+ - λˆ„μ  λΌμš΄λ“œ: **182R** (baseline v1.9.6 β†’ v1.9.225)
65
+ - ν™œλ™ κΈ°κ°„: 14일 / 평균 **13 rounds/day**
66
+ - λ‹€μŒ λ§ˆμΌμŠ€ν†€: **R200 (18 λΌμš΄λ“œ λ‚¨μŒ)**
67
+
68
+ ### 5. λˆ„μ  νšŒκ·€ (1.9.207~225) β€” λͺ¨λ‘ μœ μ§€
69
+
70
+ ### 6. stress-v171 β€” 16/16 PASS
71
+ - 1.9.226 (7): VERSION + round-history CLI + --json + git μ—†λŠ” fallback + handoff ν—€λ“œλΌμΈ + MCP 62 등둝 + MCP μ‹€ 호좜
72
+ - μ„±λŠ₯ (2): cold_start avg 336ms / round-history 535ms
73
+ - λˆ„μ  νšŒκ·€ (7): 1.9.207~225
74
+
75
+ ### 7. μžλ™ release (88 λΌμš΄λ“œ main-push streak Β· 49 λΌμš΄λ“œ npm publish streak)
76
+
77
+ πŸ”„ **자율 λΌμš΄λ“œ 진행도 κ°€μ‹œν™”** β€” handoff ν•œ μ€„μ—μ„œ λ§ˆμΌμŠ€ν†€ 예츑 κ°€λŠ₯
78
+
79
+ ---
80
+
3
81
  ## 1.9.225 β€” 2026-05-22
4
82
 
5
83
  **πŸ”§ drift check --auto-fix delivered 톡합 + LEERNESS_AUTO_APPLY_DELIVERED env opt-in.**
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.225-green)]() [![tests](https://img.shields.io/badge/e2e-217%2F217-success)]() [![stress](https://img.shields.io/badge/stress--v170-14%2F14-success)]() [![mcp](https://img.shields.io/badge/MCP--tools-61-brightgreen)]() [![rounds](https://img.shields.io/badge/autonomous--rounds-155-blueviolet)]() [![main-push](https://img.shields.io/badge/release--main--push-87_rounds-success)]() [![goal-matrix](https://img.shields.io/badge/λͺ©μ _맀트릭슀-100%2F100_(5μΆ•)-brightgreen)]() [![drift-fix](https://img.shields.io/badge/πŸ”§_drift--auto--fix-delivered_톡합-blueviolet)]() [![perf](https://img.shields.io/badge/cold_start-367ms-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.227-green)]() [![tests](https://img.shields.io/badge/e2e-217%2F217-success)]() [![stress](https://img.shields.io/badge/stress--v172-17%2F17-success)]() [![mcp](https://img.shields.io/badge/MCP--tools-62-brightgreen)]() [![rounds](https://img.shields.io/badge/autonomous--rounds-183-blueviolet)]() [![main-push](https://img.shields.io/badge/release--main--push-89_rounds-success)]() [![goal-matrix](https://img.shields.io/badge/λͺ©μ _맀트릭슀-100%2F100_(5μΆ•)-brightgreen)]() [![json-fields](https://img.shields.io/badge/πŸ“Š_JSON_톡합_ν•„λ“œ-6%2F6-blueviolet)]() [![perf](https://img.shields.io/badge/cold_start-400ms-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.225 AI Agent Reliability Harness + Sandbox β•‘
15
+ β•‘ v1.9.227 AI Agent Reliability Harness + Sandbox β•‘
16
16
  β•‘ verify Β· remember Β· orchestrate Β· audit Β· sandbox Β· drift β•‘
17
- β•‘ πŸ”§ drift --auto-fix delivered + AUTO_APPLY env opt-in β•‘
17
+ β•‘ πŸ“Š handoff/session close --json 6 톡합 ν•„λ“œ μ™„μ„± β•‘
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.225';
10
+ const VERSION = '1.9.227';
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 처리).
@@ -2054,6 +2054,84 @@ function _compareSemver(a, b) {
2054
2054
  return 0;
2055
2055
  }
2056
2056
 
2057
+ // 1.9.226: round-history β€” git tag v1.9.X 기반 자율 λΌμš΄λ“œ 톡계 + λ‹€μŒ λ§ˆμΌμŠ€ν†€
2058
+ // git이 μ—†κ±°λ‚˜ tagκ°€ μ—†μœΌλ©΄ graceful fallback (current version + 0 history)
2059
+ // 응닡: { currentVersion, roundCount, baselineVersion, latestTags[], nextMilestone, roundsToNextMilestone, firstTagAt, latestTagAt, daysActive, avgRoundsPerDay }
2060
+ function _computeRoundHistory(root) {
2061
+ const result = {
2062
+ currentVersion: VERSION,
2063
+ roundCount: 0,
2064
+ baselineVersion: null,
2065
+ latestTags: [],
2066
+ nextMilestone: null,
2067
+ roundsToNextMilestone: null,
2068
+ firstTagAt: null,
2069
+ latestTagAt: null,
2070
+ daysActive: 0,
2071
+ avgRoundsPerDay: 0
2072
+ };
2073
+ try {
2074
+ // git tag --list 'v1.9.*' --sort=creatordate (μ‹œκ°„μˆœ)
2075
+ const r = cp.spawnSync('git', ['tag', '--list', 'v1.9.*', '--sort=creatordate', '--format=%(refname:short)|%(creatordate:iso8601)'], {
2076
+ cwd: root, encoding: 'utf8', timeout: 5000
2077
+ });
2078
+ if (r.status !== 0 || !r.stdout) return result;
2079
+ const lines = r.stdout.split('\n').filter(l => l.trim() && /^v\d+\.\d+\.\d+\|/.test(l));
2080
+ if (lines.length === 0) return result;
2081
+ const tags = lines.map(l => {
2082
+ const [name, date] = l.split('|');
2083
+ return { name: name.trim(), version: name.replace(/^v/, '').trim(), date: date.trim() };
2084
+ });
2085
+ result.roundCount = tags.length;
2086
+ result.baselineVersion = tags[0].version;
2087
+ result.firstTagAt = tags[0].date;
2088
+ result.latestTagAt = tags[tags.length - 1].date;
2089
+ // 졜근 10개
2090
+ result.latestTags = tags.slice(-10).reverse().map(t => ({ version: t.version, date: t.date.split('T')[0] }));
2091
+ // λ‹€μŒ λ§ˆμΌμŠ€ν†€ (50/100/150/200/300/...)
2092
+ const milestones = [50, 75, 100, 125, 150, 175, 200, 250, 300, 400, 500];
2093
+ const next = milestones.find(m => m > result.roundCount);
2094
+ if (next != null) {
2095
+ result.nextMilestone = next;
2096
+ result.roundsToNextMilestone = next - result.roundCount;
2097
+ }
2098
+ // 일일 평균
2099
+ const first = new Date(result.firstTagAt).getTime();
2100
+ const last = new Date(result.latestTagAt).getTime();
2101
+ const days = Math.max(1, Math.floor((last - first) / 86400000));
2102
+ result.daysActive = days;
2103
+ result.avgRoundsPerDay = Math.round((result.roundCount / days) * 100) / 100;
2104
+ } catch {}
2105
+ return result;
2106
+ }
2107
+
2108
+ function roundHistoryCmd(root) {
2109
+ root = absRoot(root);
2110
+ const isTty = process.stdout && process.stdout.isTTY;
2111
+ const cy = s => isTty ? `\x1b[36m${s}\x1b[0m` : s;
2112
+ const gr = s => isTty ? `\x1b[32m${s}\x1b[0m` : s;
2113
+ const yl = s => isTty ? `\x1b[33m${s}\x1b[0m` : s;
2114
+ const dm = s => isTty ? `\x1b[2m${s}\x1b[0m` : s;
2115
+ const data = _computeRoundHistory(root);
2116
+ if (has('--json')) { log(JSON.stringify(data, null, 2)); return; }
2117
+ log(cy(`# leerness round-history (1.9.226) β€” 자율 λΌμš΄λ“œ 톡계`));
2118
+ log('');
2119
+ log(` πŸ“¦ ν˜„μž¬ 버전: ${gr(data.currentVersion)}`);
2120
+ log(` πŸ”„ λˆ„μ  λΌμš΄λ“œ: ${gr(String(data.roundCount))}`);
2121
+ if (data.baselineVersion) log(` πŸ“ baseline: v${data.baselineVersion} (${(data.firstTagAt || '').split('T')[0]})`);
2122
+ if (data.latestTagAt) log(` ⏰ 졜근 tag: ${(data.latestTagAt || '').split('T')[0]}`);
2123
+ if (data.daysActive > 0) log(` πŸ“Š ν™œλ™: ${data.daysActive}일 / 평균 ${gr(data.avgRoundsPerDay + ' rounds/day')}`);
2124
+ log('');
2125
+ if (data.nextMilestone != null) {
2126
+ log(yl(` 🎯 λ‹€μŒ λ§ˆμΌμŠ€ν†€: R${data.nextMilestone} (${data.roundsToNextMilestone} λΌμš΄λ“œ λ‚¨μŒ)`));
2127
+ } else {
2128
+ log(gr(` πŸŽ‰ λͺ¨λ“  λ§ˆμΌμŠ€ν†€ 달성 (500+)`));
2129
+ }
2130
+ log('');
2131
+ log(` 졜근 10 tags:`);
2132
+ data.latestTags.forEach(t => log(` β€’ v${t.version} (${t.date})`));
2133
+ }
2134
+
2057
2135
  // 1.9.208: ν”Œλž«νΌ/API μ œμ•½ 사전 체크 (μ‚¬μš©μž λͺ…μ‹œ)
2058
2136
  // "μ‚¬μš©μžμ˜ λͺ…령을 λ°›μœΌλ©΄, κ³ λ €ν•΄μ•Όν•˜λŠ” 뢀뢄을 λ¨Όμ € ν™•μΈν•˜κ³  μ§„ν–‰ν•˜κ²Œ ν•˜λ©΄ μ–΄λ–¨μ§€"
2059
2137
  // "νŠΉμ • ν”Œλž«νΌμ˜ API ... ν˜ΈμΆœμ†λ„κ°€ μ΄ˆλ‹Ή 5회 μ΄ν•˜λ‘œλ§Œ ν•΄μ•Όν•œλ‹€λŠ” κ·œμ •μ„ λ¨Όμ € 확인"
@@ -5825,6 +5903,18 @@ function handoff(root) {
5825
5903
  ids: delivered.candidates.map(c => c.id)
5826
5904
  };
5827
5905
  } catch {}
5906
+ // 1.9.227: roundHistory 톡합 (handoff JSON 6번째 톡합 ν•„λ“œ) β€” 자율 진행도 μ™ΈλΆ€ 회수
5907
+ try {
5908
+ const rh = _computeRoundHistory(root);
5909
+ result.roundHistory = {
5910
+ roundCount: rh.roundCount,
5911
+ baselineVersion: rh.baselineVersion,
5912
+ nextMilestone: rh.nextMilestone,
5913
+ roundsToNextMilestone: rh.roundsToNextMilestone,
5914
+ daysActive: rh.daysActive,
5915
+ avgRoundsPerDay: rh.avgRoundsPerDay
5916
+ };
5917
+ } catch {}
5828
5918
  } catch {}
5829
5919
  try {
5830
5920
  const pwState = _loadPreWakeReport(root);
@@ -5987,6 +6077,17 @@ function handoff(root) {
5987
6077
  parts.push(`🌐 official ${m.total}/${m.cacheTotal} (${ageStr}${status})`);
5988
6078
  }
5989
6079
  } catch {}
6080
+ // 17) 1.9.226: round-history ν—€λ“œλΌμΈ β€” 자율 λΌμš΄λ“œ μΉ΄μš΄ν„° + λ‹€μŒ λ§ˆμΌμŠ€ν†€ (5 λΌμš΄λ“œ 이상 μ‹œλ§Œ ν‘œμ‹œ)
6081
+ try {
6082
+ const rh = _computeRoundHistory(root);
6083
+ if (rh.roundCount >= 5) {
6084
+ let label = `πŸ”„ R${rh.roundCount}`;
6085
+ if (rh.nextMilestone != null && rh.roundsToNextMilestone <= 20) {
6086
+ label += ` β†’ R${rh.nextMilestone} (${rh.roundsToNextMilestone}R λ‚¨μŒ)`;
6087
+ }
6088
+ parts.push(label);
6089
+ }
6090
+ } catch {}
5990
6091
  // 12) 1.9.204: μžλ™ λͺ¨λ“œ ν™œμ„± ν‘œμ‹œ (μ‚¬μš©μž λͺ…μ‹œ) β€” R-0001 every-round λ£° ν™œμ„± μ‹œ ν—€λ“œλΌμΈ λ…ΈμΆœ
5991
6092
  try {
5992
6093
  const autoRule = _getAutoLoopRule(root);
@@ -9939,6 +10040,18 @@ function sessionClose(root, opts = {}) {
9939
10040
  autoCompleteAvailable: delivered.candidates.length > 0
9940
10041
  };
9941
10042
  } catch {}
10043
+ // 1.9.227: roundHistory 톡합 (session close JSON 6번째 톡합 ν•„λ“œ)
10044
+ try {
10045
+ const rh = _computeRoundHistory(root);
10046
+ jsonResult.roundHistory = {
10047
+ roundCount: rh.roundCount,
10048
+ baselineVersion: rh.baselineVersion,
10049
+ nextMilestone: rh.nextMilestone,
10050
+ roundsToNextMilestone: rh.roundsToNextMilestone,
10051
+ daysActive: rh.daysActive,
10052
+ avgRoundsPerDay: rh.avgRoundsPerDay
10053
+ };
10054
+ } catch {}
9942
10055
  } catch {}
9943
10056
  try {
9944
10057
  // 1.9.209: pre-wake-audit μžλ™ μ‹€ν–‰ + μ €μž₯ (sleep μ „ μžλ™ 점검)
@@ -13889,7 +14002,8 @@ function mcpServeCmd(root) {
13889
14002
  { name: 'leerness_intent_classify', description: '1.9.216 (1.9.213 μ‚¬μš©μž λͺ…μ‹œ) β€” μ‚¬μš©μž μ˜λ„ νŒŒμ•… + scope expansion 게이트. 응닡: { intent: precise|broad|default, signals, domain, explicitMentions, expansionCandidates, mode: dry-run }. 3원칙 μ•ˆμ „: (1) Always-Off Opt-In, (2) Dry-run κΈ°λ³Έ (μ‹€ν–‰ X), (3) λͺ…μ‹œ vs μΆ”λ‘  뢄리 라벨링. 5 도메인 (game/web/api/cli/data). μ™ΈλΆ€ AIκ°€ "이 μš”μ²­μ€ μ •ν™•νžˆ κ·Έκ²ƒλ§Œ / 포괄적 / 기본인가?"λ₯Ό 회수. 인자: { request (required), path? }', inputSchema: { type: 'object', properties: { request: { type: 'string' }, path: { type: 'string' } }, required: ['request'] } },
13890
14003
  { name: 'leerness_idempotency_audit', description: '1.9.216 (1.9.212 μ‚¬μš©μž λͺ…μ‹œ) β€” λ©±λ“±μ„± μœ„λ°˜ 탐지. 4μ˜μ—­ 점검: rule-duplicate (medium) / task-duplicate-request (medium) / user-request-duplicate (low) / wakeup-duplicate (high). 응닡: { violations[], verified[], summary: {totalViolations, high/medium/low, overall} }. μ™ΈλΆ€ AIκ°€ "μ›Œν¬μŠ€νŽ˜μ΄μŠ€μ— 쀑볡/좩돌이 μžˆλ‚˜?"λ₯Ό 회수. πŸŽ‰ MCP 58 도ꡬ λ§ˆμΌμŠ€ν†€ (50β†’58). 인자: { path? }', inputSchema: { type: 'object', properties: { path: { type: 'string' } } } },
13891
14004
  { 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' } } } },
13892
- { 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' } } } }
14005
+ { 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' } } } },
14006
+ { 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' } } } }
13893
14007
  ];
13894
14008
 
13895
14009
  function send(obj) {
@@ -14050,6 +14164,10 @@ function mcpServeCmd(root) {
14050
14164
  cliArgs = ['requests', 'auto-complete', '--path', targetPath, '--json'];
14051
14165
  if (args.apply === true) cliArgs.push('--apply');
14052
14166
  break;
14167
+ case 'leerness_round_history':
14168
+ // 1.9.226: 자율 λΌμš΄λ“œ 톡계 + λ‹€μŒ λ§ˆμΌμŠ€ν†€
14169
+ cliArgs = ['round-history', '--path', targetPath, '--json'];
14170
+ break;
14053
14171
  default:
14054
14172
  return send({ jsonrpc: '2.0', id, error: { code: -32601, message: `Unknown tool: ${name}` } });
14055
14173
  }
@@ -17681,6 +17799,8 @@ async function main() {
17681
17799
  if (cmd === 'requests') return requestsCmd(arg('--path', process.cwd()), args[1], ...args.slice(2));
17682
17800
  // 1.9.220: leerness session-resume β€” 비정상 μ’…λ£Œ 감지 + 자율 재개 κ°€μ΄λ“œ (μ‚¬μš©μž λͺ…μ‹œ)
17683
17801
  if (cmd === 'session-resume') return sessionResumeCmd(arg('--path', process.cwd()));
17802
+ // 1.9.226: leerness round-history β€” 자율 λΌμš΄λ“œ 톡계 + λ‹€μŒ λ§ˆμΌμŠ€ν†€
17803
+ if (cmd === 'round-history') return roundHistoryCmd(arg('--path', process.cwd()));
17684
17804
  // 1.9.208: leerness constraints <list|check|add> β€” ν”Œλž«νΌ/API μ œμ•½ 사전 체크 (μ‚¬μš©μž λͺ…μ‹œ)
17685
17805
  if (cmd === 'constraints') return constraintsCmd(arg('--path', process.cwd()), args[1], ...args.slice(2));
17686
17806
  // 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.225",
3
+ "version": "1.9.227",
4
4
  "description": "Leerness: λΉ„νŒŒκ΄΄ λ§ˆμ΄κ·Έλ ˆμ΄μ…˜, μžλ™ 버전 κ°μ§€Β·μ—…λ°μ΄νŠΈ, κ³„νš/μ§„ν–‰/ν•Έλ“œμ˜€ν”„ μžλ™ν™”, κ²ŒμœΌλ¦„Β·μ‹œν¬λ¦ΏΒ·μΈμ½”λ”© μžλ™ κ°€λ“œ, Claude Code μŠ¬λž˜μ‹œ 톡합을 κ°–μΆ˜ ν•œκ΅­μ–΄ μš°μ„  AI 개발 ν•˜λ„€μŠ€.",
5
5
  "keywords": [
6
6
  "leerness",