leerness 1.9.228 β†’ 1.9.229

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,43 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.9.229 β€” 2026-05-23
4
+
5
+ **🎯 leerness milestones CLI + MCP 63번째 도ꡬ (도달 λ§ˆμΌμŠ€ν†€ + ETA 예츑).**
6
+
7
+ ### 1. `leerness milestones` μƒˆ λͺ…λ Ή
8
+ - git tag 순차 λΆ„μ„μœΌλ‘œ 25/50/75/100/125/150/175/200/250/300/400/500 λ§ˆμΌμŠ€ν†€ 도달 μ‹œμ  회수
9
+ - 각 λ§ˆμΌμŠ€ν†€λ³„: `{milestone, version, reachedAt, daysFromBaseline}`
10
+ - λ‹€μŒ λ§ˆμΌμŠ€ν†€ ETA 계산 (ν˜„μž¬ 속도 κΈ°μ€€): `{milestone, roundsRemaining, etaDays, etaDate}`
11
+ - `--json` μ˜΅μ…˜
12
+ - 1.9.226 round-history ν™•μž₯ (간단 톡계 β†’ 도달 이λ ₯ + ETA)
13
+
14
+ ### 2. MCP 63번째 도ꡬ β€” `leerness_milestones`
15
+ - μ™ΈλΆ€ AIκ°€ "ν”„λ‘œμ νŠΈ λ§ˆμΌμŠ€ν†€ 진척도 + λ‹€μŒ 달성 μ˜ˆμƒμΌ" 직접 회수
16
+ - MCP 62 β†’ 63 (+1)
17
+
18
+ ### 3. μ‹€ μΈ‘μ • β€” leerness 자체 λ§ˆμΌμŠ€ν†€ 이λ ₯ (7개 달성)
19
+ - R25 β†’ v1.9.68 (2026-05-19, +11d)
20
+ - R50 β†’ v1.9.93 (2026-05-20, +11d)
21
+ - R75 β†’ v1.9.118 (2026-05-20, +11d)
22
+ - R100 β†’ v1.9.143 (2026-05-20, +11d)
23
+ - R125 β†’ v1.9.168 (2026-05-20, +12d)
24
+ - R150 β†’ v1.9.193 (2026-05-21, +12d)
25
+ - R175 β†’ v1.9.218 (2026-05-22, +14d)
26
+ - **λ‹€μŒ: R200** β€” 2026-05-24 ETA (15 λΌμš΄λ“œ λ‚¨μŒ, ~2일 ν›„)
27
+
28
+ ### 4. λˆ„μ  νšŒκ·€ (1.9.207~228) β€” λͺ¨λ‘ μœ μ§€
29
+
30
+ ### 5. stress-v174 β€” 17/17 PASS
31
+ - 1.9.229 (7): VERSION + CLI + reached ν˜•νƒœ + next ETA + git fallback + MCP 63 + μ‹€ 호좜
32
+ - μ„±λŠ₯ (2): cold_start avg 442ms / milestones 717ms
33
+ - λˆ„μ  νšŒκ·€ (8): 1.9.207~228
34
+
35
+ ### 6. μžλ™ release (91 λΌμš΄λ“œ main-push streak Β· 52 λΌμš΄λ“œ npm publish streak)
36
+
37
+ 🎯 **자율 λͺ¨λ“œ 진척도 μ‹œκ°ν™” μ™„μ„±** β€” 도달 이λ ₯ + 예츑 ETA λͺ¨λ‘ κ°€μ‹œν™”
38
+
39
+ ---
40
+
3
41
  ## 1.9.228 β€” 2026-05-23
4
42
 
5
43
  **πŸ“Š health --json roundHistory 톡합 (JSON 3 λͺ…λ Ή 일관성) + session-workflow.md drift 차단 + ν—€λ“œλΌμΈ label κ°±μ‹ .**
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.228-green)]() [![tests](https://img.shields.io/badge/e2e-217%2F217-success)]() [![stress](https://img.shields.io/badge/stress--v173-15%2F15-success)]() [![mcp](https://img.shields.io/badge/MCP--tools-62-brightgreen)]() [![rounds](https://img.shields.io/badge/autonomous--rounds-184-blueviolet)]() [![main-push](https://img.shields.io/badge/release--main--push-90_rounds-success)]() [![goal-matrix](https://img.shields.io/badge/λͺ©μ _맀트릭슀-100%2F100_(5μΆ•)-brightgreen)]() [![json-3cmd](https://img.shields.io/badge/πŸ“Š_JSON_3_λͺ…λ Ή_일관성-handoff%2Bclose%2Bhealth-blueviolet)]() [![perf](https://img.shields.io/badge/cold_start-414ms-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.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)]()
6
6
 
7
7
  ```
8
8
  ╔══════════════════════════════════════════════════════════════╗
@@ -12,9 +12,9 @@
12
12
  β•‘ β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ•”β•β•β• β–ˆβ–ˆβ•”β•β•β• β–ˆβ–ˆβ•”β•β•β–ˆβ–ˆβ•—β–ˆβ–ˆβ•‘β•šβ–ˆβ–ˆβ•—β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•”β•β•β• β•šβ•β•β•β•β–ˆβ–ˆβ•‘ β•‘
13
13
  β•‘ β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•‘ β•šβ–ˆβ–ˆβ–ˆβ–ˆβ•‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•‘ β•‘
14
14
  β•‘ β•šβ•β•β•β•β•β•β•β•šβ•β•β•β•β•β•β•β•šβ•β•β•β•β•β•β•β•šβ•β• β•šβ•β•β•šβ•β• β•šβ•β•β•β•β•šβ•β•β•β•β•β•β•β•šβ•β•β•β•β•β•β• β•‘
15
- β•‘ v1.9.228 AI Agent Reliability Harness + Sandbox β•‘
15
+ β•‘ v1.9.229 AI Agent Reliability Harness + Sandbox β•‘
16
16
  β•‘ verify Β· remember Β· orchestrate Β· audit Β· sandbox Β· drift β•‘
17
- β•‘ πŸ“Š health --json roundHistory + 3 λͺ…λ Ή 일관성 μ™„μ„± β•‘
17
+ β•‘ 🎯 milestones CLI Β· MCP 63 Β· 도달 이λ ₯ + ETA 예츑 β•‘
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.228';
10
+ const VERSION = '1.9.229';
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 처리).
@@ -2105,6 +2105,97 @@ function _computeRoundHistory(root) {
2105
2105
  return result;
2106
2106
  }
2107
2107
 
2108
+ // 1.9.229: milestones β€” λ„λ‹¬ν•œ λ§ˆμΌμŠ€ν†€ 일자 + λ‹€μŒ λ§ˆμΌμŠ€ν†€ μ˜ˆμƒ μ‹œμ  (1.9.226 round-history ν™•μž₯)
2109
+ // git tag 순차 뢄석 β†’ 50/75/100/... 도달 μ‹œμ μ˜ tag 와 일자 회수
2110
+ // 응닡: { reached: [{milestone, version, reachedAt, daysFromBaseline}], next: {milestone, roundsRemaining, eta}, totalRounds, avgRoundsPerDay }
2111
+ function _computeMilestones(root) {
2112
+ const result = {
2113
+ totalRounds: 0,
2114
+ reached: [],
2115
+ next: null,
2116
+ avgRoundsPerDay: 0,
2117
+ baselineAt: null
2118
+ };
2119
+ try {
2120
+ const r = cp.spawnSync('git', ['tag', '--list', 'v1.9.*', '--sort=creatordate', '--format=%(refname:short)|%(creatordate:iso8601)'], {
2121
+ cwd: root, encoding: 'utf8', timeout: 5000
2122
+ });
2123
+ if (r.status !== 0 || !r.stdout) return result;
2124
+ const lines = r.stdout.split('\n').filter(l => l.trim() && /^v\d+\.\d+\.\d+\|/.test(l));
2125
+ if (lines.length === 0) return result;
2126
+ const tags = lines.map(l => {
2127
+ const [name, date] = l.split('|');
2128
+ return { name: name.trim(), version: name.replace(/^v/, '').trim(), date: date.trim() };
2129
+ });
2130
+ result.totalRounds = tags.length;
2131
+ result.baselineAt = tags[0].date;
2132
+ const milestones = [25, 50, 75, 100, 125, 150, 175, 200, 250, 300, 400, 500];
2133
+ const baselineTime = new Date(tags[0].date).getTime();
2134
+ // 1-indexed: tags[0] is round 1
2135
+ for (const m of milestones) {
2136
+ if (m <= tags.length) {
2137
+ const t = tags[m - 1];
2138
+ const reachedTime = new Date(t.date).getTime();
2139
+ const daysFromBaseline = Math.floor((reachedTime - baselineTime) / 86400000);
2140
+ result.reached.push({
2141
+ milestone: m,
2142
+ version: t.version,
2143
+ reachedAt: t.date.split(' ')[0],
2144
+ daysFromBaseline
2145
+ });
2146
+ }
2147
+ }
2148
+ // λ‹€μŒ λ§ˆμΌμŠ€ν†€ + 평균 μ†λ„λ‘œ ETA 계산
2149
+ const lastTime = new Date(tags[tags.length - 1].date).getTime();
2150
+ const days = Math.max(1, Math.floor((lastTime - baselineTime) / 86400000));
2151
+ const avgPerDay = (tags.length / days);
2152
+ result.avgRoundsPerDay = Math.round(avgPerDay * 100) / 100;
2153
+ const nextM = milestones.find(m => m > tags.length);
2154
+ if (nextM != null) {
2155
+ const roundsRemaining = nextM - tags.length;
2156
+ const etaDays = avgPerDay > 0 ? Math.ceil(roundsRemaining / avgPerDay) : null;
2157
+ const etaDate = etaDays != null ? new Date(Date.now() + etaDays * 86400000).toISOString().split('T')[0] : null;
2158
+ result.next = { milestone: nextM, roundsRemaining, etaDays, etaDate };
2159
+ }
2160
+ } catch {}
2161
+ return result;
2162
+ }
2163
+
2164
+ function milestonesCmd(root) {
2165
+ root = absRoot(root);
2166
+ const isTty = process.stdout && process.stdout.isTTY;
2167
+ const cy = s => isTty ? `\x1b[36m${s}\x1b[0m` : s;
2168
+ const gr = s => isTty ? `\x1b[32m${s}\x1b[0m` : s;
2169
+ const yl = s => isTty ? `\x1b[33m${s}\x1b[0m` : s;
2170
+ const dm = s => isTty ? `\x1b[2m${s}\x1b[0m` : s;
2171
+ const data = _computeMilestones(root);
2172
+ if (has('--json')) { log(JSON.stringify(data, null, 2)); return; }
2173
+ log(cy(`# leerness milestones (1.9.229) β€” 도달 λ§ˆμΌμŠ€ν†€ + λ‹€μŒ ETA`));
2174
+ log('');
2175
+ log(` πŸ“¦ 총 λΌμš΄λ“œ: ${gr(String(data.totalRounds))}`);
2176
+ if (data.baselineAt) log(` πŸ“ baseline: ${(data.baselineAt || '').split(' ')[0]}`);
2177
+ if (data.avgRoundsPerDay) log(` πŸ“Š 평균: ${gr(data.avgRoundsPerDay + ' rounds/day')}`);
2178
+ log('');
2179
+ if (data.reached.length === 0) {
2180
+ log(dm(` (도달 λ§ˆμΌμŠ€ν†€ μ—†μŒ β€” 첫 R25 λ§ˆμΌμŠ€ν†€ μ§„ν–‰ 쀑)`));
2181
+ } else {
2182
+ log(` 도달 λ§ˆμΌμŠ€ν†€ ${data.reached.length}개:`);
2183
+ for (const m of data.reached) {
2184
+ log(` βœ“ R${m.milestone} ${gr(`(v${m.version}, ${m.reachedAt}, +${m.daysFromBaseline}d)`)}`);
2185
+ }
2186
+ }
2187
+ log('');
2188
+ if (data.next) {
2189
+ log(yl(` 🎯 λ‹€μŒ λ§ˆμΌμŠ€ν†€: R${data.next.milestone}`));
2190
+ log(` β€’ ${data.next.roundsRemaining} λΌμš΄λ“œ λ‚¨μŒ`);
2191
+ if (data.next.etaDays != null) {
2192
+ log(` β€’ ETA: ${data.next.etaDate} (~${data.next.etaDays}일 ν›„, ν˜„μž¬ 속도 κΈ°μ€€)`);
2193
+ }
2194
+ } else {
2195
+ log(gr(` πŸŽ‰ λͺ¨λ“  λ§ˆμΌμŠ€ν†€ 달성 (500+)`));
2196
+ }
2197
+ }
2198
+
2108
2199
  function roundHistoryCmd(root) {
2109
2200
  root = absRoot(root);
2110
2201
  const isTty = process.stdout && process.stdout.isTTY;
@@ -14003,7 +14094,8 @@ function mcpServeCmd(root) {
14003
14094
  { 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' } } } },
14004
14095
  { 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' } } } },
14005
14096
  { 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' } } } }
14097
+ { 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' } } } }
14007
14099
  ];
14008
14100
 
14009
14101
  function send(obj) {
@@ -14168,6 +14260,10 @@ function mcpServeCmd(root) {
14168
14260
  // 1.9.226: 자율 λΌμš΄λ“œ 톡계 + λ‹€μŒ λ§ˆμΌμŠ€ν†€
14169
14261
  cliArgs = ['round-history', '--path', targetPath, '--json'];
14170
14262
  break;
14263
+ case 'leerness_milestones':
14264
+ // 1.9.229: 도달 λ§ˆμΌμŠ€ν†€ + λ‹€μŒ ETA
14265
+ cliArgs = ['milestones', '--path', targetPath, '--json'];
14266
+ break;
14171
14267
  default:
14172
14268
  return send({ jsonrpc: '2.0', id, error: { code: -32601, message: `Unknown tool: ${name}` } });
14173
14269
  }
@@ -17813,6 +17909,8 @@ async function main() {
17813
17909
  if (cmd === 'session-resume') return sessionResumeCmd(arg('--path', process.cwd()));
17814
17910
  // 1.9.226: leerness round-history β€” 자율 λΌμš΄λ“œ 톡계 + λ‹€μŒ λ§ˆμΌμŠ€ν†€
17815
17911
  if (cmd === 'round-history') return roundHistoryCmd(arg('--path', process.cwd()));
17912
+ // 1.9.229: leerness milestones β€” 도달 λ§ˆμΌμŠ€ν†€ + λ‹€μŒ ETA (1.9.226 ν™•μž₯)
17913
+ if (cmd === 'milestones') return milestonesCmd(arg('--path', process.cwd()));
17816
17914
  // 1.9.208: leerness constraints <list|check|add> β€” ν”Œλž«νΌ/API μ œμ•½ 사전 체크 (μ‚¬μš©μž λͺ…μ‹œ)
17817
17915
  if (cmd === 'constraints') return constraintsCmd(arg('--path', process.cwd()), args[1], ...args.slice(2));
17818
17916
  // 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.228",
3
+ "version": "1.9.229",
4
4
  "description": "Leerness: λΉ„νŒŒκ΄΄ λ§ˆμ΄κ·Έλ ˆμ΄μ…˜, μžλ™ 버전 κ°μ§€Β·μ—…λ°μ΄νŠΈ, κ³„νš/μ§„ν–‰/ν•Έλ“œμ˜€ν”„ μžλ™ν™”, κ²ŒμœΌλ¦„Β·μ‹œν¬λ¦ΏΒ·μΈμ½”λ”© μžλ™ κ°€λ“œ, Claude Code μŠ¬λž˜μ‹œ 톡합을 κ°–μΆ˜ ν•œκ΅­μ–΄ μš°μ„  AI 개발 ν•˜λ„€μŠ€.",
5
5
  "keywords": [
6
6
  "leerness",