leerness 1.9.200 β†’ 1.9.202

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,107 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.9.202 β€” 2026-05-22
4
+
5
+ **🌐 CμΆ• (곡식 ν‘œμ€€ μŠ€ν‚¬ μžλ™ ν™œμš©) 9.0/10 β†’ 9.5/10 보강 β€” matched skill μ„€μΉ˜ μƒνƒœ ν‘œμ‹œ + leerness skill install-top.**
6
+
7
+ 자율 λͺ¨λ“œ 132 λΌμš΄λ“œ. 100% 맀트릭슀 도전 β€” CμΆ• λ§ˆμ§€λ§‰ 0.5 보강 (97 β†’ 97.5).
8
+
9
+ ### 1. install 이λ ₯ 기둝 + μ„€μΉ˜ μƒνƒœ ν‘œμ‹œ
10
+ - `.harness/skill-installed-log.json` (λΉ„μ‹œν¬λ¦Ώ, 체크인 κ°€λŠ₯)
11
+ - ν•¨μˆ˜: `_loadSkillInstalledLog` / `_appendSkillInstalledLog` / `_isSkillInstalled`
12
+ - handoff matched entry 에 `βœ“ μ„€μΉ˜λ¨` λ˜λŠ” `πŸ†•` νƒœκ·Έ μžλ™ ν‘œμ‹œ
13
+
14
+ ### 2. `leerness skill install-top` μ‹ κ·œ CLI
15
+ - handoff μ»¨ν…μŠ€νŠΈ (in-progress task) 의 keyword 둜 official skill λ§€μΉ­
16
+ - top 1 (이미 μ„€μΉ˜λœ 것 μžλ™ skip) μ¦‰μ‹œ download + install
17
+ - μ„€μΉ˜ ν›„ μžλ™ 이λ ₯ 기둝 β†’ 쀑볡 install λ°©μ§€
18
+ - `--force`: 이미 μ„€μΉ˜λœ 것 κ°•μ œ μž¬μ„€μΉ˜
19
+
20
+ ### 3. handoff body 톡합
21
+ ```
22
+ ## 🌐 곡식 organization μŠ€ν‚¬ μžλ™ λ§€μΉ­ (1.9.192/193) β€” ν‚€μ›Œλ“œ "X"
23
+ βœ“ μ„€μΉ˜λ¨ [vercel] skill-A β€” ...
24
+ πŸ†• [anthropic] skill-B β€” ...
25
+ β†’ 1개 μ¦‰μ‹œ: leerness skill install-top (1.9.202)
26
+ β†’ 전체 μ„€μΉ˜: leerness skill auto-install --yes
27
+ ```
28
+
29
+ ### 4. λˆ„μ  νšŒκ·€ (1.9.196~201) β€” λͺ¨λ‘ μœ μ§€
30
+
31
+ ### 5. stress-v147 β€” 15/15 PASS
32
+ - μ„€μΉ˜ 이λ ₯ (6) + μ„±λŠ₯ (2) + λˆ„μ  νšŒκ·€ (7)
33
+ - μ„±λŠ₯: --version cold start avg **457 ms** Β· MCP 54 도ꡬ **468 ms**
34
+
35
+ ### 6. 5μΆ• 맀트릭슀
36
+ | μΆ• | 1.9.201 | 1.9.202 | μƒνƒœ |
37
+ |---|---|---|---|
38
+ | C. 곡식 ν‘œμ€€ μŠ€ν‚¬ μžλ™ ν™œμš© | 9.0 | **9.5** | +0.5 (μ„€μΉ˜ μƒνƒœ + install-top) |
39
+ | **μ’…ν•©** | 48.5/50 (97%) | **49/50 (98%)** | **+1%** |
40
+
41
+ ### 7. μžλ™ release
42
+ - main μžλ™ push **64 λΌμš΄λ“œ 연속** (1.9.140~202)
43
+ - npm publish μžλ™ (1.9.178~)
44
+
45
+ ---
46
+
47
+ ## 1.9.201 β€” 2026-05-22
48
+
49
+ **🎯 EμΆ• (κ²ŒμœΌλ¦„ λ°©μ§€) 9.5/10 β†’ 10/10 보강 β€” next-action queue + leerness next-action take λͺ…λ Ή.**
50
+
51
+ 자율 λͺ¨λ“œ 131 λΌμš΄λ“œ. 200 λ§ˆμΌμŠ€ν†€ 후속 β€” 100% 맀트릭슀λ₯Ό ν–₯ν•œ λ‹€μŒ 단계.
52
+
53
+ ### μ‚¬μš©μž μ˜λ„ μ •λ ¬ (1.9.191 verbatim)
54
+ > *"κ²ŒμœΌλ¦„ λ°©μ§€λ“±λ“± 졜고의 도ꡬ"*
55
+
56
+ ### 1. handoff next-action μžλ™ νμž‰ (EμΆ• 핡심)
57
+ - `_suggestNextActions` (1.9.194) κ°€ μ œμ•ˆν•œ ν•­λͺ©μ„ `.harness/next-action-queue.json` 에 μžλ™ μ €μž₯
58
+ - 쀑볡 λ°©μ§€ (이미 μžˆλŠ” title skip), 졜근 20개만 μœ μ§€
59
+ - ν•¨μˆ˜: `_enqueueNextActions(root, actions)` / `_loadNextActionQueue(root)` / `_writeNextActionQueue(root, queue)`
60
+
61
+ ### 2. `leerness next-action` μ‹ κ·œ CLI
62
+ - `next-action list [--json]` β€” 큐 전체 (default sub)
63
+ - `next-action take [N]` β€” νμ—μ„œ κ°€μ Έμ™€μ„œ `leerness task add` μžλ™ 호좜 (N μƒλž΅ μ‹œ μ΅œμ‹ )
64
+ - `next-action add "<text>"` β€” μˆ˜λ™ μΆ”κ°€
65
+ - `next-action clear` β€” 큐 μ΄ˆκΈ°ν™”
66
+
67
+ ### 3. 1-step κ²ŒμœΌλ¦„ λ°©μ§€ 흐름
68
+ ```
69
+ $ leerness handoff .
70
+ ## 🎯 λ‹€μŒ 단계 μžλ™ μ œμ•ˆ (1.9.194 EμΆ•) β€” ν‚€μ›Œλ“œ "X"
71
+ πŸ›‘ κ³Όκ±° μ‹€νŒ¨ νšŒν”Ό β€” lessons.md "X" κ΄€λ ¨ N건
72
+ `leerness lessons --auto --path .`
73
+ β†’ μ¦‰μ‹œ task add: leerness next-action take (큐 +1건 μ €μž₯됨, 1.9.201)
74
+
75
+ $ leerness next-action take
76
+ βœ“ task μΆ”κ°€: T-0042 β€” "κ³Όκ±° μ‹€νŒ¨ νšŒν”Ό β€” lessons.md..."
77
+ πŸ’‘ μ‹€ν–‰ λͺ…λ Ή: leerness lessons --auto --path .
78
+ ```
79
+
80
+ ### 4. λˆ„μ  νšŒκ·€ (1.9.195~200) β€” λͺ¨λ‘ μœ μ§€
81
+
82
+ ### 5. stress-v146 β€” 16/16 PASS
83
+ - next-action CLI (7) + μž„μ‹œ μ›Œν¬μŠ€νŽ˜μ΄μŠ€ 톡합 (1) + μ„±λŠ₯ (2) + λˆ„μ  νšŒκ·€ (7)
84
+ - μ„±λŠ₯: --version cold start avg **436 ms** Β· MCP 54 도ꡬ **442 ms**
85
+
86
+ ### 6. 5μΆ• 맀트릭슀 변동
87
+ | μΆ• | 1.9.200 | 1.9.201 | Ξ” |
88
+ |---|---|---|---|
89
+ | E. κ²ŒμœΌλ¦„ λ°©μ§€ | 9.5/10 | **10/10** βœ“ | +0.5 (next-action 1-step μžλ™ task add) |
90
+ | **μ’…ν•©** | 48/50 (96%) | **48.5/50 (97%)** | +1% |
91
+
92
+ ### 7. 5μΆ• λͺ¨λ‘ 9 이상 + 3μΆ• 10/10
93
+ - A 10/10 βœ“ (1.9.197)
94
+ - D 10/10 βœ“ (1.9.196)
95
+ - E 10/10 βœ“ (1.9.201) β€” μ‹ κ·œ
96
+ - B 9.5/10 (1.9.198)
97
+ - C 9.0/10 (1.9.192)
98
+
99
+ ### 8. μžλ™ release 흐름
100
+ - main μžλ™ push **63 λΌμš΄λ“œ 연속** (1.9.140~201)
101
+ - npm publish μžλ™ (1.9.178~)
102
+
103
+ ---
104
+
3
105
  ## 1.9.200 β€” 2026-05-22
4
106
 
5
107
  **πŸŽ‰ 200 λ§ˆμΌμŠ€ν†€ β€” 60 λΌμš΄λ“œ 자율 λˆ„μ  + 5μΆ• 맀트릭슀 96/100.**
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.200-green)]() [![tests](https://img.shields.io/badge/e2e-217%2F217-success)]() [![stress](https://img.shields.io/badge/stress--v145-13%2F13-success)]() [![mcp](https://img.shields.io/badge/MCP--tools-54-brightgreen)]() [![rounds](https://img.shields.io/badge/autonomous--rounds-130-blueviolet)]() [![main-push](https://img.shields.io/badge/release--main--push-62_rounds-success)]() [![goal-matrix](https://img.shields.io/badge/λͺ©μ _맀트릭슀-96%2F100_(5μΆ•)-brightgreen)]() [![milestone](https://img.shields.io/badge/πŸŽ‰-1.9.200_60_λΌμš΄λ“œ_λ§ˆμΌμŠ€ν†€-gold)]() [![perf](https://img.shields.io/badge/cold_start-1022ms-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.202-green)]() [![tests](https://img.shields.io/badge/e2e-217%2F217-success)]() [![stress](https://img.shields.io/badge/stress--v147-15%2F15-success)]() [![mcp](https://img.shields.io/badge/MCP--tools-54-brightgreen)]() [![rounds](https://img.shields.io/badge/autonomous--rounds-132-blueviolet)]() [![main-push](https://img.shields.io/badge/release--main--push-64_rounds-success)]() [![goal-matrix](https://img.shields.io/badge/λͺ©μ _맀트릭슀-98%2F100_(5μΆ•)-brightgreen)]() [![skill-install-top](https://img.shields.io/badge/skill-install--top_μ¦‰μ‹œ-success)]() [![perf](https://img.shields.io/badge/cold_start-457ms-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.200 AI Agent Reliability Harness + Sandbox β•‘
15
+ β•‘ v1.9.202 AI Agent Reliability Harness + Sandbox β•‘
16
16
  β•‘ verify Β· remember Β· orchestrate Β· audit Β· sandbox Β· drift β•‘
17
- β•‘ πŸŽ‰ 200 λ§ˆμΌμŠ€ν†€ Β· 맀트릭슀 96/100 Β· 130 λΌμš΄λ“œ Β· 62 push 연속 β•‘
17
+ β•‘ 🌐 skill install-top + μ„€μΉ˜ μƒνƒœ Β· 맀트릭슀 98/100 Β· AΒ·DΒ·E 10/10 β•‘
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.200';
10
+ const VERSION = '1.9.202';
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 처리).
@@ -1556,6 +1556,77 @@ async function skillDiscoverCmd(root) {
1556
1556
  log(`πŸ’‘ μ„€μΉ˜: leerness skill install <url>`);
1557
1557
  }
1558
1558
 
1559
+ // 1.9.202: CμΆ• (곡식 ν‘œμ€€ μŠ€ν‚¬ μžλ™ ν™œμš©) 9.0β†’9.5 보강 β€” install 이λ ₯ 기둝 + μ„€μΉ˜ μƒνƒœ ν‘œμ‹œ
1560
+ // 1.9.192 official catalog λ§€μΉ­ μ‹œ "이미 μ„€μΉ˜λ¨" / "μ‹ κ·œ" ꡬ뢄 β†’ 쀑볡 install λ°©μ§€ + μ‚¬μš©μž 인지 도움
1561
+ // 파일: .harness/skill-installed-log.json (λΉ„μ‹œν¬λ¦Ώ)
1562
+ function _skillInstalledLogPath(root) { return path.join(root, '.harness', 'skill-installed-log.json'); }
1563
+ function _loadSkillInstalledLog(root) {
1564
+ try {
1565
+ const fp = _skillInstalledLogPath(root);
1566
+ if (!exists(fp)) return { installed: [] };
1567
+ const j = JSON.parse(read(fp));
1568
+ return { installed: Array.isArray(j.installed) ? j.installed : [] };
1569
+ } catch { return { installed: [] }; }
1570
+ }
1571
+ function _appendSkillInstalledLog(root, entry) {
1572
+ try {
1573
+ const state = _loadSkillInstalledLog(root);
1574
+ const e = { name: entry.name, source: entry.source || entry.preset || '?', url: entry.url || '', at: new Date().toISOString() };
1575
+ // 쀑볡 (같은 name + source) 제거 ν›„ append
1576
+ state.installed = state.installed.filter(x => !(x.name === e.name && x.source === e.source));
1577
+ state.installed.push(e);
1578
+ mkdirp(path.join(root, '.harness'));
1579
+ writeUtf8(_skillInstalledLogPath(root), JSON.stringify({ installed: state.installed }, null, 2));
1580
+ return true;
1581
+ } catch { return false; }
1582
+ }
1583
+ function _isSkillInstalled(root, entry) {
1584
+ try {
1585
+ const state = _loadSkillInstalledLog(root);
1586
+ const src = entry.source || entry.preset || '?';
1587
+ return state.installed.some(x => x.name === entry.name && x.source === src);
1588
+ } catch { return false; }
1589
+ }
1590
+
1591
+ // 1.9.202: leerness skill install-top β€” handoff matched 의 top 1 entry λ₯Ό μ¦‰μ‹œ install
1592
+ async function skillInstallTopCmd(root) {
1593
+ root = absRoot(root);
1594
+ // handoff context 의 keyword μΆ”μΆœ
1595
+ const rows = readProgressRows(root);
1596
+ const active = rows.find(r => r.status === 'in-progress' || r.status === '[μ§„ν–‰]') || rows[rows.length - 1];
1597
+ if (!active || !active.request) { fail('in-progress task μ—†μŒ β€” leerness handoff . λ¨Όμ €'); return process.exit(1); }
1598
+ const m = _matchOfficialSkillsFromCache(root, active.request, 3);
1599
+ if (m.entries.length === 0) {
1600
+ fail(`맀칭된 official skill μ—†μŒ (keyword: "${(active.request || '').slice(0, 40)}", cache total: ${m.cacheTotal || 0})`);
1601
+ return process.exit(1);
1602
+ }
1603
+ // 이미 μ„€μΉ˜λœ 것 skip
1604
+ const candidates = m.entries.filter(e => !_isSkillInstalled(root, e));
1605
+ if (candidates.length === 0) {
1606
+ log(`βœ“ λͺ¨λ“  맀칭된 skill 이미 μ„€μΉ˜λ¨ (1.9.202 log κΈ°μ€€):`);
1607
+ for (const e of m.entries) log(` β€’ ${e.name} (${e.preset || e.source}) β€” 이미 μ„€μΉ˜`);
1608
+ log(` β†’ leerness skill install-top --force 둜 μž¬μ„€μΉ˜`);
1609
+ return;
1610
+ }
1611
+ const top = has('--force') ? m.entries[0] : candidates[0];
1612
+ log(`# leerness skill install-top (1.9.202 CμΆ• 보강)`);
1613
+ log(` task: ${(active.request || '').slice(0, 80)}`);
1614
+ log(` λ§€μΉ­: ${m.total}/${m.cacheTotal}건 Β· top 1 β†’ ${top.name} (${top.preset || top.source})`);
1615
+ log(` URL: ${top.url || '(none)'}`);
1616
+ log('');
1617
+ if (!top.url) { fail(`top entry url λΆ€μž¬ β€” install λΆˆκ°€`); return process.exit(1); }
1618
+ try {
1619
+ log(`πŸ“₯ install μ‹œμž‘...`);
1620
+ await skillInstallCmd(root, top.url);
1621
+ _appendSkillInstalledLog(root, top);
1622
+ log('');
1623
+ log(`βœ“ μ„€μΉ˜ + 이λ ₯ 기둝 μ™„λ£Œ (.harness/skill-installed-log.json)`);
1624
+ } catch (e) {
1625
+ fail(`install μ‹€νŒ¨: ${e.message}`);
1626
+ return process.exit(1);
1627
+ }
1628
+ }
1629
+
1559
1630
  // 1.9.182: skill auto-install β€” 곡식 organization catalog μžλ™ 탐색 β†’ skill match β†’ μžλ™ install.
1560
1631
  // μ‚¬μš©μž λͺ…μ‹œ: "μŠ€ν‚¬μ„ μ‚¬μš©ν•˜κ±°λ‚˜ μ μš©ν•΄λ‘λ©΄ 쒋을 뢀뢄듀을 μ•Œμ•„μ„œ μ›Ήμ—μ„œ 곡식 쑰직의 μŠ€ν‚¬ λͺ¨μŒμ„ νƒμƒ‰ν•΄μ„œ λ‹€μš΄λ‘œλ“œ λ°›μ•„μ„œ μ‚¬μš©"
1561
1632
  // μ •μ±…: LEERNESS_SKILL_AUTO_INSTALL=1 일 λ•Œλ§Œ μ‹€μ œ install (λ³΄μ•ˆ opt-in). λ―Έμ„€μ • μ‹œ dry-run (μΆ”μ²œλ§Œ).
@@ -1733,6 +1804,110 @@ function _loadMultiAgentConsensusHistory(root, keyword) {
1733
1804
  } catch { return []; }
1734
1805
  }
1735
1806
 
1807
+ // 1.9.201: EμΆ• (κ²ŒμœΌλ¦„ λ°©μ§€) 9.5β†’10 보강 β€” next-action queue μžλ™ μ €μž₯ + take λͺ…λ Ή
1808
+ // handoff κ°€ μ œμ•ˆν•œ next-action top ν•­λͺ©μ„ .harness/next-action-queue.json 에 μ €μž₯ β†’
1809
+ // `leerness next-action take` 호좜 μ‹œ νμ—μ„œ pop + leerness task add μžλ™ μ‹€ν–‰ β†’
1810
+ // AI/μ‚¬μš©μžκ°€ 직접 좔적/타이핑 없이 1-step 으둜 task μ§„μž…
1811
+ function _nextActionQueuePath(root) { return path.join(root, '.harness', 'next-action-queue.json'); }
1812
+ function _loadNextActionQueue(root) {
1813
+ try {
1814
+ const fp = _nextActionQueuePath(root);
1815
+ if (!exists(fp)) return { queue: [], at: null };
1816
+ const j = JSON.parse(read(fp));
1817
+ return { queue: Array.isArray(j.queue) ? j.queue : [], at: j.at || null };
1818
+ } catch { return { queue: [], at: null }; }
1819
+ }
1820
+ function _writeNextActionQueue(root, queue) {
1821
+ try {
1822
+ mkdirp(path.join(root, '.harness'));
1823
+ writeUtf8(_nextActionQueuePath(root), JSON.stringify({ queue, at: new Date().toISOString() }, null, 2));
1824
+ return true;
1825
+ } catch { return false; }
1826
+ }
1827
+ // handoff μ—μ„œ μ œμ•ˆλœ next-action 듀을 큐에 μžλ™ μ €μž₯ (쀑볡 λ°©μ§€: 이미 μžˆλŠ” title 은 skip)
1828
+ function _enqueueNextActions(root, actions) {
1829
+ if (!Array.isArray(actions) || actions.length === 0) return 0;
1830
+ const state = _loadNextActionQueue(root);
1831
+ const existingTitles = new Set(state.queue.map(a => a.title));
1832
+ let added = 0;
1833
+ for (const a of actions) {
1834
+ if (existingTitles.has(a.title)) continue;
1835
+ state.queue.push({ ...a, addedAt: new Date().toISOString() });
1836
+ existingTitles.add(a.title);
1837
+ added++;
1838
+ }
1839
+ // 졜근 20개만 μœ μ§€
1840
+ if (state.queue.length > 20) state.queue = state.queue.slice(-20);
1841
+ if (added > 0) _writeNextActionQueue(root, state.queue);
1842
+ return added;
1843
+ }
1844
+
1845
+ // 1.9.201: next-action CLI λͺ…λ Ή β€” handoff κ°€ μ €μž₯ν•œ queue μ—μ„œ take/list/clear
1846
+ async function nextActionCmd(root, sub, ...rest) {
1847
+ root = absRoot(root);
1848
+ const state = _loadNextActionQueue(root);
1849
+ if (!sub || sub === 'list') {
1850
+ if (has('--json')) { log(JSON.stringify(state, null, 2)); return; }
1851
+ log(`# leerness next-action list (1.9.201)`);
1852
+ if (state.queue.length === 0) {
1853
+ log(' (큐 λΉ„μ–΄μžˆμŒ)');
1854
+ log(` β†’ handoff κ°€ μžλ™μœΌλ‘œ 큐에 μ €μž₯ν•©λ‹ˆλ‹€. \`leerness handoff .\` ν›„ λ‹€μ‹œ 확인.`);
1855
+ return;
1856
+ }
1857
+ log(` 큐 ${state.queue.length}건 (생성: ${state.at || '?'})`);
1858
+ log('');
1859
+ for (let i = 0; i < state.queue.length; i++) {
1860
+ const a = state.queue[i];
1861
+ log(` [${i}] ${a.icon || 'β€’'} ${a.title}`);
1862
+ if (a.command) log(` \`${a.command}\``);
1863
+ }
1864
+ log('');
1865
+ log(` β†’ κ°€μ Έμ˜€κΈ°: leerness next-action take [N] (N μƒλž΅ μ‹œ μ΅œμ‹  [${state.queue.length - 1}])`);
1866
+ return;
1867
+ }
1868
+ if (sub === 'take') {
1869
+ const n = rest[0] !== undefined ? Number(rest[0]) : state.queue.length - 1;
1870
+ if (state.queue.length === 0) { fail('큐 λΉ„μ–΄μžˆμŒ β€” handoff λ¨Όμ € μ‹€ν–‰'); return process.exit(1); }
1871
+ if (isNaN(n) || n < 0 || n >= state.queue.length) { fail(`잘λͺ»λœ index: ${n} (0~${state.queue.length - 1})`); return process.exit(1); }
1872
+ const action = state.queue[n];
1873
+ log(`# leerness next-action take [${n}] (1.9.201)`);
1874
+ log(` ${action.icon || 'β€’'} ${action.title}`);
1875
+ if (action.command) log(` \`${action.command}\``);
1876
+ // task add μžλ™ 호좜
1877
+ try {
1878
+ const taskTitle = action.title.replace(/^[^\wκ°€-힣]+/, '').slice(0, 100);
1879
+ // νμ—μ„œ 제거 β†’ write
1880
+ state.queue.splice(n, 1);
1881
+ _writeNextActionQueue(root, state.queue);
1882
+ // leerness task add 호좜
1883
+ const taskResult = cp.spawnSync(process.execPath, [__filename, 'task', 'add', taskTitle, '--path', root], { encoding: 'utf8', timeout: 8000 });
1884
+ if (taskResult.status === 0) {
1885
+ const m = (taskResult.stdout || '').match(/T-\d{4}/);
1886
+ log(` βœ“ task μΆ”κ°€: ${m ? m[0] : '?'} β€” "${taskTitle}"`);
1887
+ if (action.command) log(` πŸ’‘ μ‹€ν–‰ λͺ…λ Ή: ${action.command}`);
1888
+ } else {
1889
+ log(` ⚠ task add μ‹€νŒ¨ (exit ${taskResult.status}) β€” μˆ˜λ™: leerness task add "${taskTitle}"`);
1890
+ }
1891
+ } catch (e) {
1892
+ log(` ⚠ 처리 μ‹€νŒ¨: ${e.message}`);
1893
+ }
1894
+ return;
1895
+ }
1896
+ if (sub === 'clear') {
1897
+ _writeNextActionQueue(root, []);
1898
+ ok(`next-action 큐 μ΄ˆκΈ°ν™” (${state.queue.length}건 제거)`);
1899
+ return;
1900
+ }
1901
+ if (sub === 'add') {
1902
+ const title = rest.filter(x => !x.startsWith('-')).join(' ').trim();
1903
+ if (!title) return fail('μ‚¬μš©λ²•: leerness next-action add "<text>"');
1904
+ _enqueueNextActions(root, [{ icon: 'πŸ“', title, command: null }]);
1905
+ ok(`next-action μΆ”κ°€: ${title}`);
1906
+ return;
1907
+ }
1908
+ fail(`μ•Œ 수 μ—†λŠ” sub: ${sub} (list / take / clear / add)`);
1909
+ }
1910
+
1736
1911
  // 1.9.194: EμΆ• (κ²ŒμœΌλ¦„ λ°©μ§€) β€” handoff μ—μ„œ λ‹€μŒ 단계 1-3개 μžλ™ μ œμ•ˆ
1737
1912
  // ν˜„μž¬ in-progress task description + Memory Surface (decisions/lessons/plan) μ‘°ν•© β†’
1738
1913
  // "λ‹€μŒ λ‹¨κ³„λ‘œ 무엇을 ν• μ§€" μΆ”λ‘  (μ‚¬μš©μž/AI 직접 μž…λ ₯ 없이 μ¦‰μ‹œ λ…ΈμΆœ)
@@ -3731,10 +3906,14 @@ function handoff(root) {
3731
3906
  log(cyan(`## 🌐 곡식 organization μŠ€ν‚¬ μžλ™ λ§€μΉ­ (1.9.192/193) β€” ν‚€μ›Œλ“œ "${keyword}"`));
3732
3907
  const ageLabel = veryStale ? yel(`${cacheAge} ⚠ 7일+`) : (ofm.expired ? yel(`${cacheAge} ⚠ 만료`) : `${cacheAge} βœ“`);
3733
3908
  log(dim(` vercel-labs/anthropics λ“± catalog μΊμ‹œ ${ageLabel} Β· ${ofm.total}/${ofm.cacheTotal}건 λ§€μΉ­`));
3909
+ // 1.9.202: 각 entry 의 μ„€μΉ˜ μƒνƒœ ν‘œμ‹œ (installed/new)
3734
3910
  for (const e of ofm.entries) {
3735
- log(dim(` β€’ [${e.preset || e.source || '?'}] ${e.name} β€” ${(e.description || '').slice(0, 70)}`));
3911
+ const installed = _isSkillInstalled(root, e);
3912
+ const tag = installed ? 'βœ“ μ„€μΉ˜λ¨' : 'πŸ†•';
3913
+ log(dim(` ${tag} [${e.preset || e.source || '?'}] ${e.name} β€” ${(e.description || '').slice(0, 65)}`));
3736
3914
  }
3737
- log(dim(` β†’ μ„€μΉ˜: leerness skill auto-install --yes`));
3915
+ log(dim(` β†’ 1개 μ¦‰μ‹œ: leerness skill install-top (1.9.202)`));
3916
+ log(dim(` β†’ 전체 μ„€μΉ˜: leerness skill auto-install --yes`));
3738
3917
  if (ofm.expired || veryStale) log(yel(` β†’ κ°±μ‹  ꢌμž₯: leerness skill auto-cache refresh (1.9.193 ${veryStale ? '7일+ stale' : '24h+ expired'})`));
3739
3918
  log('');
3740
3919
  } else if (ofm.cacheTotal === 0) {
@@ -3765,6 +3944,11 @@ function handoff(root) {
3765
3944
  log(dim(` ${a.icon} ${a.title}`));
3766
3945
  if (a.command) log(dim(` \`${a.command}\``));
3767
3946
  }
3947
+ // 1.9.201: queue μžλ™ μ €μž₯ β€” `leerness next-action take` 둜 μ¦‰μ‹œ task add κ°€λŠ₯
3948
+ try {
3949
+ const added = _enqueueNextActions(root, actions);
3950
+ if (added > 0) log(dim(` β†’ μ¦‰μ‹œ task add: leerness next-action take (큐 +${added}건 μ €μž₯됨, 1.9.201)`));
3951
+ } catch {}
3768
3952
  log(dim(` β†’ 직접 μž…λ ₯: leerness next-action add "<text>"`));
3769
3953
  log('');
3770
3954
  }
@@ -14766,6 +14950,8 @@ async function main() {
14766
14950
  if (cmd === 'skill' && args[1] === 'suggest') return skillSuggestCmd(absRoot(arg('--path', process.cwd())));
14767
14951
  // 1.9.182: leerness skill auto-install β€” 곡식 catalog μžλ™ 탐색 + skill match λ§€μΉ­ μ‹œ μžλ™ install (μ‚¬μš©μž λͺ…μ‹œ)
14768
14952
  if (cmd === 'skill' && args[1] === 'auto-install') return await skillAutoInstallCmd(absRoot(arg('--path', process.cwd())));
14953
+ // 1.9.202: leerness skill install-top β€” handoff matched top 1 μ¦‰μ‹œ install (CμΆ• 9β†’9.5 보강)
14954
+ if (cmd === 'skill' && args[1] === 'install-top') return await skillInstallTopCmd(absRoot(arg('--path', process.cwd())));
14769
14955
  // 1.9.192: skill auto-cache β€” 곡식 organization catalog 24h μΊμ‹œ 관리 (CμΆ• 보강)
14770
14956
  if (cmd === 'skill' && args[1] === 'auto-cache') return await skillAutoCacheCmd(absRoot(arg('--path', process.cwd())), args[2] || 'status');
14771
14957
  if (cmd === 'mcp' && args[1] === 'serve') return mcpServeCmd(absRoot(arg('--path', process.cwd())));
@@ -14777,6 +14963,8 @@ async function main() {
14777
14963
  if (cmd === 'brainstorm') return brainstormCmd(arg('--path', process.cwd()), args.slice(1).filter(x => !x.startsWith('-')).join(' '));
14778
14964
  if (cmd === 'roadmap' && args[1] === 'auto') return roadmapAutoCmd(arg('--path', process.cwd()), args[2]);
14779
14965
  if (cmd === 'roadmap') return roadmapCmd(args[1] || process.cwd());
14966
+ // 1.9.201: next-action queue CLI (EμΆ• 9.5β†’10)
14967
+ if (cmd === 'next-action') return nextActionCmd(arg('--path', process.cwd()), args[1], ...args.slice(2));
14780
14968
  if (cmd === 'rule' && args[1] === 'add') return ruleAdd(arg('--path', process.cwd()), args.slice(2).filter(x => !x.startsWith('-')).join(' '));
14781
14969
  if (cmd === 'rule' && args[1] === 'list') return ruleList(arg('--path', process.cwd()));
14782
14970
  if (cmd === 'rule' && args[1] === 'remove') return ruleRemove(arg('--path', process.cwd()), args[2]);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "leerness",
3
- "version": "1.9.200",
3
+ "version": "1.9.202",
4
4
  "description": "Leerness: λΉ„νŒŒκ΄΄ λ§ˆμ΄κ·Έλ ˆμ΄μ…˜, μžλ™ 버전 κ°μ§€Β·μ—…λ°μ΄νŠΈ, κ³„νš/μ§„ν–‰/ν•Έλ“œμ˜€ν”„ μžλ™ν™”, κ²ŒμœΌλ¦„Β·μ‹œν¬λ¦ΏΒ·μΈμ½”λ”© μžλ™ κ°€λ“œ, Claude Code μŠ¬λž˜μ‹œ 톡합을 κ°–μΆ˜ ν•œκ΅­μ–΄ μš°μ„  AI 개발 ν•˜λ„€μŠ€.",
5
5
  "keywords": [
6
6
  "leerness",