leerness 1.9.181 โ†’ 1.9.183

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,180 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.9.183 โ€” 2026-05-21
4
+
5
+ **๐Ÿ“ฆ npm i leerness + ๊ตฌ๋ฒ„์ „ ์ž๋™ ๊ฐ์ง€/๊ฒฝ๊ณ /์—…๋ฐ์ดํŠธ ๋ช…๋ น์–ด ์•ˆ๋‚ด (์‚ฌ์šฉ์ž ๋ช…์‹œ 3์ข…).**
6
+
7
+ ์ž์œจ ๋ชจ๋“œ 113 ๋ผ์šด๋“œ. ์‚ฌ์šฉ์ž ๋ช…์‹œ:
8
+ 1. *"(vercel/anthropic) ํ‘œ๊ธฐ๋Š” ์ œ๊ฑฐ"* โ†’ ์ผ๋ฐ˜ํ™”
9
+ 2. *"vercel/anthropic ํฌํ•จํ•œ ๋‹ค๋ฅธ ๊ณต์‹ ์Šคํ‚ฌ๋„ ์ž๋™ ํƒ์ƒ‰ํ•˜๋Š” ๊ฒŒ ๋งž๋Š”์ง€ ํ™•์ธ"* โ†’ ๊ฒ€์ฆ ํ†ต๊ณผ
10
+ 3. *"npm i leerness ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•˜๊ฒŒ + ๊ตฌ๋ฒ„์ „ ๊ฐ์ง€/๊ฒฝ๊ณ /์—…๋ฐ์ดํŠธ ๋ช…๋ น์–ด ์•ˆ๋‚ด"* โ†’ ๋ชจ๋“  ๋ช…๋ น์— stale check ์ง„์ž…
11
+
12
+ ### 1. ํ‘œ๊ธฐ ์ผ๋ฐ˜ํ™”
13
+ ```diff
14
+ - ๐ŸŒ ๊ณต์‹ catalog ์ž๋™ ํƒ์ƒ‰ (vercel/anthropic) ยท ์ž๊ฐ€ ์„ฑ์žฅํ˜•
15
+ + ๐ŸŒ ๊ณต์‹ catalog ์ž๋™ ํƒ์ƒ‰ ยท ์ž๊ฐ€ ์„ฑ์žฅํ˜• ยท ๊ตฌ๋ฒ„์ „ ๊ฐ์ง€/์•ˆ๋‚ด
16
+ ```
17
+
18
+ ### 2. ๋‹ค๋ฅธ ๊ณต์‹ catalog ์ž๋™ ํƒ์ƒ‰ ํ™•์ธ (live)
19
+ ```bash
20
+ $ leerness skill discover --all-presets
21
+ fetching vercel-labs/agent-skills...
22
+ โœ“ vercel-labs/agent-skills: 8๊ฐœ skill ๋ฐœ๊ฒฌ
23
+ fetching anthropics/skills...
24
+ โœ“ anthropics/skills: 17๊ฐœ skill ๋ฐœ๊ฒฌ
25
+ ์ „์ฒด 25๊ฑด
26
+ ```
27
+ **vercel + anthropic ๋ชจ๋‘ ์ •์ƒ ์ž‘๋™**. ๋‹ค๋ฅธ ๊ณต์‹ organization์€ `--github <owner/repo>` ์˜ต์…˜์œผ๋กœ ์ฆ‰์‹œ ์ถ”๊ฐ€ ๊ฐ€๋Šฅ (`vercel-labs/agent-skills`, `anthropics/skills` ์™ธ์— ์ƒˆ ๊ณต์‹ ๋“ฑ์žฅ ์‹œ preset ๋“ฑ๋ก).
28
+
29
+ ์กฐ์‚ฌ ๊ฒฐ๊ณผ โ€” 1.9.183 ์‹œ์  ํ‘œ์ค€ SKILL.md ์นดํƒˆ๋กœ๊ทธ๋ฅผ ๊ฐ–์ถ˜ ๊ณต์‹ organization:
30
+ - `vercel-labs/agent-skills` (8๊ฐœ) โ† preset `vercel`
31
+ - `anthropics/skills` (17๊ฐœ) โ† preset `anthropic`
32
+ - `modelcontextprotocol/servers` โ€” SKILL.md ํ˜•์‹ ์•„๋‹˜ (MCP server ๊ตฌํ˜„ โ€” leerness skill ํ˜ธํ™˜์„ฑ X)
33
+ - ๊ธฐํƒ€ โ€” ๋ฏธ๋ฐœ๊ฒฌ. ์ƒˆ ๊ณต์‹ ๋“ฑ์žฅ ์‹œ ์ฆ‰์‹œ preset ๋“ฑ๋ก ๊ฐ€๋Šฅ.
34
+
35
+ ### 3. ๊ตฌ๋ฒ„์ „ ์ž๋™ ๊ฐ์ง€ ๊ฐ•ํ™” (๋ชจ๋“  ๋ช…๋ น)
36
+ **Before**: init/migrate ์‹œ์ ๋งŒ stale check (๋‹ค๋ฅธ ๋ช…๋ น์€ skip)
37
+ **After**: ๊ฑฐ์˜ ๋ชจ๋“  ๋ช…๋ น ์‹œ์ ์— stale check (init/migrate/mcp/release/version/help ์ œ์™ธ โ€” ์ถœ๋ ฅ ๋ฏผ๊ฐ ๋ช…๋ น์€ skip)
38
+
39
+ ```js
40
+ // 1.9.183 (์‚ฌ์šฉ์ž ๋ช…์‹œ): ๋ชจ๋“  ๋ช…๋ น ์‹œ์ ์—์„œ ๊ตฌ๋ฒ„์ „ ๊ฐ์ง€ + ๊ฒฝ๊ณ  + ์—…๋ฐ์ดํŠธ ๋ช…๋ น์–ด ์•ˆ๋‚ด
41
+ const _staleSkip = new Set(['init', 'migrate', 'usage', 'mcp', 'release', 'session-close', '--version', '--help', 'help', 'update', 'whats-new']);
42
+ if (!_staleSkip.has(cmd) && process.env.LEERNESS_NO_STALE_CHECK !== '1' && !has('--no-stale-check')) {
43
+ const cached = readUpdateCache(root);
44
+ if (cacheFresh(cached, 24) && cached.nextLeerness && compareVer(cached.nextLeerness, VERSION) > 0) {
45
+ process.stderr.write(` โš  leerness v${VERSION} โ†’ v${cached.nextLeerness} ์‚ฌ์šฉ ๊ฐ€๋Šฅ ยท npm i leerness@latest ๊ถŒ์žฅ ...`);
46
+ }
47
+ }
48
+ ```
49
+
50
+ **์‹ค ๋™์ž‘ ๊ฒ€์ฆ** (์บ์‹œ ์‹œ๋ฎฌ๋ ˆ์ด์…˜):
51
+ ```
52
+ $ leerness audit .
53
+ โš  leerness v1.9.183 โ†’ v1.9.999 ์‚ฌ์šฉ ๊ฐ€๋Šฅ ยท npm i leerness@latest ๊ถŒ์žฅ (LEERNESS_NO_STALE_CHECK=1 ๋กœ ๋„๊ธฐ)
54
+ โœ“ no duplicate design guide candidates
55
+ [...]
56
+ ```
57
+
58
+ ### 4. `npm i leerness` ์ฒซ ๊ถŒ์žฅ (๊ธ€๋กœ๋ฒŒ โ†’ ๋กœ์ปฌ ์šฐ์„ )
59
+ init ์‹œ์  stale ๋ฉ”์‹œ์ง€๋„ ๊ฐฑ์‹ :
60
+ ```
61
+ ํ•ด๊ฒฐ โ€” ์…‹ ์ค‘ ํ•˜๋‚˜ ์‹คํ–‰ ํ›„ ๋‹ค์‹œ ์‹œ๋„:
62
+ npm i leerness@latest # ํ”„๋กœ์ ํŠธ ๋กœ์ปฌ ์„ค์น˜ (1.9.183 ๊ถŒ์žฅ)
63
+ npm i -g leerness@latest # ๊ธ€๋กœ๋ฒŒ ์„ค์น˜
64
+ npx --yes clear-npx-cache && npx leerness@latest init .
65
+ ```
66
+
67
+ ### npm registry ์ƒํƒœ
68
+ ```bash
69
+ $ npm view leerness version
70
+ 1.9.182 โ† ์ง์ „ publish
71
+ $ npm view leerness dist-tags
72
+ { latest: '1.9.182' }
73
+ ```
74
+ ์ด๋ฒˆ ๋ผ์šด๋“œ release sync-main ํ›„ `latest: '1.9.183'` ์œผ๋กœ ์ž๋™ ๊ฐฑ์‹ .
75
+
76
+ ### Verified
77
+ - stress-v128: **16/16** (์‚ฌ์šฉ์ž ๋ช…์‹œ 3 + ๊ตฌ๋ฒ„์ „ ๊ฐ์ง€ 4 + npm ๋ฐฐํฌ 2 + VERSION+๋ˆ„์  7)
78
+ - e2e 217/217 baseline ์œ ์ง€
79
+ - VERSION = 1.9.183 ยท autonomous-rounds = 113 ยท main ์ž๋™ push 44 ๋ผ์šด๋“œ ์—ฐ์†
80
+
81
+ ---
82
+
83
+ ## 1.9.182 โ€” 2026-05-21
84
+
85
+ **๐ŸŒ ๊ณต์‹ ์กฐ์ง ์Šคํ‚ฌ catalog ์ž๋™ ํƒ์ƒ‰ โ€” vercel-labs/agent-skills + anthropics/skills ์ง์ ‘ ํ†ตํ•ฉ (์‚ฌ์šฉ์ž ๋ช…์‹œ).**
86
+
87
+ ์ž์œจ ๋ชจ๋“œ 112 ๋ผ์šด๋“œ. ์‚ฌ์šฉ์ž ๋ช…์‹œ: *"๊ณต์‹ ์กฐ์ง์˜ ์Šคํ‚ฌ ๋ชจ์Œ์„ ํƒ์ƒ‰ํ•ด์„œ ๋‹ค์šด๋กœ๋“œ ๋ฐ›์•„์„œ ์Šคํ‚ฌ์„ ์‚ฌ์šฉํ•˜๋Š”์ง€ ํ™•์ธ (vercel-labs/agent-skills, anthropics/skills) + ์ง€๊ธˆ ์„ค๊ณ„ํ•˜๋Š” ๋ฐฉํ–ฅ์ด ์˜ฌ๋ฐ”๋ฅธ์ง€ ํŒ๋‹จ๋„ ๋„ˆ๊ฐ€ ํ•ด์ค˜"*.
88
+
89
+ ### ํ•ต์‹ฌ ์ถ”๊ฐ€
90
+
91
+ #### 1. `SKILL_CATALOG_PRESETS` โ€” ๋‚ด์žฅ ๊ณต์‹ catalog
92
+ ```js
93
+ const SKILL_CATALOG_PRESETS = {
94
+ 'vercel': { owner: 'vercel-labs', repo: 'agent-skills', branch: 'main', path: 'skills' },
95
+ 'anthropic': { owner: 'anthropics', repo: 'skills', branch: 'main', path: 'skills' }
96
+ };
97
+ ```
98
+
99
+ #### 2. `_fetchGitHubSkills(owner, repo, branch, dirPath)` โ€” GitHub Contents API ์ง์ ‘ ํ˜ธ์ถœ
100
+ - rate limit: 60 req/hr (LEERNESS_GITHUB_TOKEN ์‹œ 5000 req/hr)
101
+ - ์‘๋‹ต์„ ํ‘œ์ค€ entry ํ˜•์‹์œผ๋กœ ๋ณ€ํ™˜ (name, url, description, source, homepage)
102
+ - raw.githubusercontent.com URL ์ž๋™ ๊ตฌ์„ฑ
103
+
104
+ #### 3. `leerness skill discover` ํ™•์žฅ
105
+ ```bash
106
+ $ leerness skill discover --preset anthropic
107
+ # leerness skill discover (1.9.182 โ€” GitHub presets)
108
+ targets: anthropics/skills#main:skills
109
+ fetching anthropics/skills...
110
+ โœ“ anthropics/skills: 17๊ฐœ skill ๋ฐœ๊ฒฌ
111
+ ์ „์ฒด 17๊ฑด (์ „์ฒด ํ‘œ์‹œ โ€” ๋งค์นญ ์—†์Œ)
112
+
113
+ | name | source | url |
114
+ |---|---|---|
115
+ | algorithmic-art | github:anthropics/skills | https://raw.githubusercontent.com/anthropics/skills/main/skills/algorithmic-art/SKILL.md |
116
+ | mcp-builder | github:anthropics/skills | https://raw.githubusercontent.com/anthropics/skills/main/skills/mcp-builder/SKILL.md |
117
+ | ...
118
+ ```
119
+
120
+ ์‹ ๊ทœ ์˜ต์…˜:
121
+ - `--preset <name>` โ€” ๋‚ด์žฅ catalog (vercel, anthropic)
122
+ - `--all-presets` โ€” ๋ชจ๋“  preset ๋™์‹œ ํƒ์ƒ‰
123
+ - `--github owner/repo[#branch][:path]` โ€” ์ง์ ‘ GitHub repo ์ง€์ •
124
+
125
+ #### 4. `leerness skill auto-install` โ€” ์‹ ๊ทœ ๋ช…๋ น (์‚ฌ์šฉ์ž ๋ช…์‹œ ํ•ต์‹ฌ)
126
+ ```bash
127
+ $ leerness skill auto-install --query "mcp"
128
+ # leerness skill auto-install (1.9.182)
129
+ presets: vercel, anthropic
130
+ query: mcp
131
+ mode: ๐ŸŸก dry-run (LEERNESS_SKILL_AUTO_INSTALL=1 ๋˜๋Š” --yes ํ•„์š”)
132
+ fetching anthropics/skills...
133
+ โœ“ anthropics/skills: 17๊ฐœ skill
134
+ ๋งค์นญ 1/17๊ฑด (query: mcp)
135
+ | mcp-builder | github:anthropics/skills | https://raw.githubusercontent.com/anthropics/skills/main/skills/mcp-builder/SKILL.md |
136
+
137
+ ๐Ÿ’ก ์ž๋™ install ํ™œ์„ฑํ™”: .env ์— LEERNESS_SKILL_AUTO_INSTALL=1 ๋˜๋Š” leerness skill auto-install --yes
138
+ ```
139
+
140
+ - handoff ์ปจํ…์ŠคํŠธ์—์„œ ์ž๋™ query ์ถ”์ถœ (์ง„ํ–‰ task ํ‚ค์›Œ๋“œ)
141
+ - LEERNESS_SKILL_AUTO_INSTALL=1 ์‹œ ์‹ค์ œ ๋‹ค์šด๋กœ๋“œ (๋ณด์•ˆ opt-in)
142
+ - ๋ฏธ์„ค์ • ์‹œ dry-run (์ถ”์ฒœ๋งŒ)
143
+
144
+ #### 5. .env.example ๋ณด๊ฐ•
145
+ ```
146
+ LEERNESS_SKILL_AUTO_INSTALL=0
147
+ LEERNESS_SKILL_AUTO_PRESETS=vercel,anthropic
148
+ ```
149
+
150
+ ### ์‹ค ๊ฒ€์ฆ (live GitHub API)
151
+ - **anthropics/skills 17๊ฐœ skill ์ž๋™ ๋ฐœ๊ฒฌ**:
152
+ algorithmic-art, brand-guidelines, canvas-design, claude-api, doc-coauthoring, **docx**, frontend-design, internal-comms, **mcp-builder**, **pdf**, **pptx**, skill-creator, slack-gif-creator, theme-factory, web-artifacts-builder, **webapp-testing**, **xlsx**
153
+ - **mcp-builder ์‹ค ๋‹ค์šด๋กœ๋“œ + ์„ค์น˜ ์„ฑ๊ณต**:
154
+ `leerness-stress/.harness/skills/mcp-builder/SKILL.md` ๋‹ค์šด๋กœ๋“œ ๊ฒ€์ฆ
155
+ description: "Guide for creating high-quality MCP (Model Context Protocol) servers..."
156
+
157
+ ### ๋ฐฉํ–ฅ์„ฑ ํ‰๊ฐ€ ๋ณด๊ณ ์„œ (์‚ฌ์šฉ์ž ๋ช…์‹œ)
158
+ ์‚ฌ์šฉ์ž ์š”์ฒญ: *"์ง€๊ธˆ ์„ค๊ณ„ํ•˜๋Š” ๋ฐฉํ–ฅ์ด ์˜ฌ๋ฐ”๋ฅธ ๋ฐฉํ–ฅ์ธ์ง€ ํŒ๋‹จ๋„ ๋„ˆ๊ฐ€ ํ•ด์ค˜"*. ๋ณด๊ณ ์„œ: `_reports/direction-1.9.182.md` (๋น„๊ณต๊ฐœ).
159
+
160
+ **๊ฒฐ๋ก **:
161
+ | ํ‰๊ฐ€ ํ•ญ๋ชฉ | ์ ์ˆ˜ |
162
+ |---|---|
163
+ | ์ž์œจ์„ฑ (auto loop ยท review ยท install) | 8.5/10 |
164
+ | ์„ฑ์žฅ์„ฑ (learn ยท suggest ยท skill catalog) | 8/10 |
165
+ | ์•ˆ์ „์„ฑ (sandbox ยท permissions ยท env opt-in) | 9/10 |
166
+ | ๋ฒ”์šฉ์„ฑ (multi-provider ยท MCP ยท bridges) | 8/10 |
167
+ | ๊ฒ€์ฆ ๊ฐ€๋Šฅ์„ฑ (verify-claim ยท stress ยท e2e) | 9.5/10 |
168
+
169
+ **์ข…ํ•ฉ**: 86/100. **์˜ฌ๋ฐ”๋ฅธ ๋ฐฉํ–ฅ**. ์•ฝ์ ์€ *์Šคํ‚ฌ ์ ์šฉ ํ›„ ํšŒ๊ณ  ๋ถ€์žฌ + ์™ธ๋ถ€ ์Šคํ‚ฌ ์‹ ๋ขฐ์„ฑ ๊ฒ€์ฆ* โ€” 1.9.183~190 ๋งˆ์ผ์Šคํ†ค.
170
+
171
+ ### Verified
172
+ - stress-v127: **16/16** (preset 4 + .env ๋ผ์šฐํŒ… 2 + ์‹ค GitHub fetch 3 + VERSION+๋ˆ„์  ํšŒ๊ท€ 7)
173
+ - e2e 217/217 baseline ์œ ์ง€
174
+ - VERSION = 1.9.182 ยท autonomous-rounds = 112 ยท main ์ž๋™ push 43 ๋ผ์šด๋“œ ์—ฐ์†
175
+
176
+ ---
177
+
3
178
  ## 1.9.181 โ€” 2026-05-21
4
179
 
5
180
  **๐Ÿšช REPL ์ง„์ž… ํ๋ฆ„ ์ •๋ฆฌ โ€” ์‚ฌ์šฉ์ž ๋ช…์‹œ 4์ข… + ์ง์ ‘ ๊ตฌ๋™ ์‹ค ํ˜ธ์ถœ ๊ฒ€์ฆ.**
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.181-green)]() [![tests](https://img.shields.io/badge/e2e-217%2F217-success)]() [![stress](https://img.shields.io/badge/stress--v126-18%2F18-success)]() [![mcp](https://img.shields.io/badge/MCP--tools-54-brightgreen)]() [![rounds](https://img.shields.io/badge/autonomous--rounds-111-blueviolet)]() [![main-push](https://img.shields.io/badge/release--main--push-42_rounds-success)]() [![repl-flow](https://img.shields.io/badge/REPL_์ง„์ž…-provider_์ž๋™์„ ํƒ-success)]() [![repl-tested](https://img.shields.io/badge/์‹คํ˜ธ์ถœ-claude_๊ฒ€์ฆ-success)]() [![npm-auto](https://img.shields.io/badge/npm_auto--publish-NPM__TOKEN_ํ†ตํ•ฉ-success)]() [![capability](https://img.shields.io/badge/6_capability-72%25_production--ready-brightgreen)]() [![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.183-green)]() [![tests](https://img.shields.io/badge/e2e-217%2F217-success)]() [![stress](https://img.shields.io/badge/stress--v128-16%2F16-success)]() [![mcp](https://img.shields.io/badge/MCP--tools-54-brightgreen)]() [![rounds](https://img.shields.io/badge/autonomous--rounds-113-blueviolet)]() [![main-push](https://img.shields.io/badge/release--main--push-44_rounds-success)]() [![install](https://img.shields.io/badge/npm_i_leerness-์ฆ‰์‹œ_์‚ฌ์šฉ_๊ฐ€๋Šฅ-success)]() [![stale-check](https://img.shields.io/badge/๊ตฌ๋ฒ„์ „_๊ฐ์ง€-๋ชจ๋“ _๋ช…๋ น_์‹œ์ -success)]() [![skill-presets](https://img.shields.io/badge/skill_catalog-๊ณต์‹_2์ข…%2B--github_ํ™•์žฅ-success)]() [![direction](https://img.shields.io/badge/๋ฐฉํ–ฅ์„ฑ_ํ‰๊ฐ€-86%2F100-brightgreen)]() [![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.181 AI Agent Reliability Harness + Sandbox โ•‘
15
+ โ•‘ v1.9.183 AI Agent Reliability Harness + Sandbox โ•‘
16
16
  โ•‘ verify ยท remember ยท orchestrate ยท audit ยท sandbox ยท drift โ•‘
17
- โ•‘ ๐Ÿšช REPL ์ง„์ž… ํ๋ฆ„ ์ •๋ฆฌ (provider ์ž๋™ ์„ ํƒ ยท ์‹คํ˜ธ์ถœ ๊ฒ€์ฆ) โ•‘
17
+ โ•‘ ๐ŸŒ ๊ณต์‹ catalog ์ž๋™ ํƒ์ƒ‰ ยท ์ž๊ฐ€ ์„ฑ์žฅํ˜• ยท ๊ตฌ๋ฒ„์ „ ๊ฐ์ง€/์•ˆ๋‚ด โ•‘
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.181';
10
+ const VERSION = '1.9.183';
11
11
  const MARK = '<!-- leerness:managed -->';
12
12
  const README_START = '<!-- leerness:project-readme:start -->';
13
13
  const README_END = '<!-- leerness:project-readme:end -->';
@@ -872,7 +872,11 @@ async function install(root, opts = {}) {
872
872
  '# ์˜ˆ์‹œ URL: https://agentskills.io/llms.txt',
873
873
  'LEERNESS_SKILL_DISCOVER_URL=',
874
874
  '# (์„ ํƒ) ์‚ฌ์šฉ์ž ์š”์ฒญ ๋ถ„์„ ์‹œ ์ž๋™ ๋งค์นญ ์Šคํ‚ฌ ์ถ”์ฒœ. 1=ํ™œ์„ฑ, 0/๋ฏธ์„ค์ •=๋น„ํ™œ์„ฑ.',
875
- 'LEERNESS_SKILL_AUTO_DISCOVER=0'
875
+ 'LEERNESS_SKILL_AUTO_DISCOVER=0',
876
+ '# 1.9.182 โ€” handoff ์‹œ ๊ณต์‹ catalog (vercel-labs, anthropics) ์ž๋™ ํƒ์ƒ‰ + ๋งค์นญ ์‹œ ์ž๋™ install. 1=ํ™œ์„ฑ (opt-in ๋ณด์•ˆ).',
877
+ 'LEERNESS_SKILL_AUTO_INSTALL=0',
878
+ '# 1.9.182 โ€” handoff ์ž๋™ ํƒ์ƒ‰ ๋Œ€์ƒ preset (์ฝค๋งˆ ๊ตฌ๋ถ„). ์˜ˆ: vercel,anthropic',
879
+ 'LEERNESS_SKILL_AUTO_PRESETS=vercel,anthropic'
876
880
  ];
877
881
  mergeLinesFile(path.join(root, '.env.example'), envLines);
878
882
  // 1.9.153: .env ์ง์ ‘ ์ƒ์„ฑ/๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ (์‚ฌ์šฉ์ž ๋ช…์‹œ ์š”์ฒญ). ๋ณด์•ˆ = ๋นˆ ๊ฐ’๋งŒ โ€” ์‚ฌ์šฉ์ž๊ฐ€ ์ง์ ‘ ํ† ํฐ ์ฑ„์›€.
@@ -1322,15 +1326,135 @@ function _parseSkillCatalog(body, sourceUrl) {
1322
1326
  return entries;
1323
1327
  }
1324
1328
 
1325
- // skill discover โ€” agentskills.io ๋˜๋Š” ์‚ฌ์šฉ์ž ์ง€์ • URL์˜ ์นดํƒˆ๋กœ๊ทธ ์ธ๋ฑ์Šค์—์„œ ๋งค์นญ ์ถ”์ฒœ
1329
+ // 1.9.182: ๊ณต์‹ ์กฐ์ง ์Šคํ‚ฌ catalog presets โ€” ์‚ฌ์šฉ์ž ๋ช…์‹œ (vercel-labs, anthropics ๊ฐ™์€ 1st-party ์ž๋™ ํƒ์ƒ‰).
1330
+ // ๊ฐ entry: GitHub repo์˜ skills/ ๋””๋ ‰ํ† ๋ฆฌ์— SKILL.md ๋“ค์ด ์žˆ๋Š” ํ‘œ์ค€ ๊ตฌ์กฐ.
1331
+ // sync: leerness skill discover --preset <name> ยท --all-presets ยท --github <owner/repo>[#branch]
1332
+ const SKILL_CATALOG_PRESETS = {
1333
+ 'vercel': { owner: 'vercel-labs', repo: 'agent-skills', branch: 'main', path: 'skills',
1334
+ homepage: 'https://github.com/vercel-labs/agent-skills' },
1335
+ 'anthropic': { owner: 'anthropics', repo: 'skills', branch: 'main', path: 'skills',
1336
+ homepage: 'https://github.com/anthropics/skills' }
1337
+ };
1338
+
1339
+ // 1.9.182: GitHub repo ์˜ skills/ ๋””๋ ‰ํ† ๋ฆฌ ์ž๋™ ํƒ์ƒ‰.
1340
+ // GitHub Contents API (no auth 60req/hr, .env GITHUB_TOKEN ์‹œ 5000req/hr) ์‚ฌ์šฉ.
1341
+ // ์‘๋‹ต์„ ํ‘œ์ค€ entry ํ˜•์‹์œผ๋กœ ๋ณ€ํ™˜: { name, url, description, format: 'github', source }
1342
+ async function _fetchGitHubSkills(owner, repo, branch, dirPath) {
1343
+ branch = branch || 'main'; dirPath = dirPath || 'skills';
1344
+ const apiUrl = `https://api.github.com/repos/${owner}/${repo}/contents/${dirPath}?ref=${branch}`;
1345
+ const token = process.env.LEERNESS_GITHUB_TOKEN || process.env.GITHUB_TOKEN || '';
1346
+ const headers = token ? { Authorization: `Bearer ${token}` } : {};
1347
+ // _httpFetch ๊ฐ€ headers๋ฅผ ์ง€์›ํ•˜์ง€ ์•Š์œผ๋ฉด raw https ์‚ฌ์šฉ
1348
+ let body, status;
1349
+ try {
1350
+ const https = require('https');
1351
+ const u = new URL(apiUrl);
1352
+ body = await new Promise((resolve, reject) => {
1353
+ const req = https.get({
1354
+ hostname: u.hostname, path: u.pathname + u.search,
1355
+ headers: { 'User-Agent': `leerness/${VERSION}`, ...headers }
1356
+ }, res => {
1357
+ status = res.statusCode;
1358
+ const chunks = [];
1359
+ res.on('data', c => chunks.push(c));
1360
+ res.on('end', () => resolve(Buffer.concat(chunks).toString('utf8')));
1361
+ });
1362
+ req.on('error', reject);
1363
+ req.setTimeout(10000, () => { req.destroy(new Error('timeout')); });
1364
+ });
1365
+ } catch (e) { return { ok: false, error: e.message, skills: [] }; }
1366
+ if (status !== 200) return { ok: false, error: `HTTP ${status}`, skills: [] };
1367
+ let items; try { items = JSON.parse(body); } catch { return { ok: false, error: 'invalid JSON', skills: [] }; }
1368
+ if (!Array.isArray(items)) return { ok: false, error: 'not array', skills: [] };
1369
+ const skills = items
1370
+ .filter(i => i && i.type === 'dir')
1371
+ .map(i => ({
1372
+ name: i.name,
1373
+ url: `https://raw.githubusercontent.com/${owner}/${repo}/${branch}/${i.path}/SKILL.md`,
1374
+ description: '',
1375
+ format: 'github',
1376
+ source: `github:${owner}/${repo}`,
1377
+ homepage: i.html_url
1378
+ }));
1379
+ return { ok: true, skills };
1380
+ }
1381
+
1382
+ // skill discover โ€” agentskills.io / GitHub repo / ๊ณต์‹ preset ์นดํƒˆ๋กœ๊ทธ ์ธ๋ฑ์Šค์—์„œ ๋งค์นญ ์ถ”์ฒœ
1326
1383
  async function skillDiscoverCmd(root) {
1327
- const url = arg('--source', null) || process.env.LEERNESS_SKILL_DISCOVER_URL || null;
1384
+ // 1.9.182: --preset / --all-presets / --github ์ถ”๊ฐ€ (์‚ฌ์šฉ์ž ๋ช…์‹œ โ€” vercel-labs/agent-skills, anthropics/skills ๋“ฑ)
1385
+ const preset = arg('--preset', null);
1386
+ const allPresets = has('--all-presets');
1387
+ const github = arg('--github', null); // ์˜ˆ: vercel-labs/agent-skills ๋˜๋Š” owner/repo#branch:path
1328
1388
  const query = arg('--query', null);
1389
+
1390
+ // preset / --all-presets / --github ์ฒ˜๋ฆฌ โ€” ๋‹จ์ผ source URL๊ณผ ๋ณ„๊ฐœ ํ๋ฆ„
1391
+ if (preset || allPresets || github) {
1392
+ const targets = [];
1393
+ if (allPresets) for (const k of Object.keys(SKILL_CATALOG_PRESETS)) targets.push({ key: k, ...SKILL_CATALOG_PRESETS[k] });
1394
+ else if (preset) {
1395
+ const p = SKILL_CATALOG_PRESETS[preset];
1396
+ if (!p) { fail(`์•Œ ์ˆ˜ ์—†๋Š” preset: ${preset} (์‚ฌ์šฉ ๊ฐ€๋Šฅ: ${Object.keys(SKILL_CATALOG_PRESETS).join(', ')})`); return process.exit(1); }
1397
+ targets.push({ key: preset, ...p });
1398
+ }
1399
+ if (github) {
1400
+ // owner/repo ๋˜๋Š” owner/repo#branch ๋˜๋Š” owner/repo#branch:path
1401
+ const m = github.match(/^([^/]+)\/([^#:]+)(?:#([^:]+))?(?::(.+))?$/);
1402
+ if (!m) { fail(`--github ํ˜•์‹ ์˜ค๋ฅ˜ (์˜ˆ: vercel-labs/agent-skills ๋˜๋Š” owner/repo#main:skills)`); return process.exit(1); }
1403
+ targets.push({ key: 'custom', owner: m[1], repo: m[2], branch: m[3] || 'main', path: m[4] || 'skills', homepage: `https://github.com/${m[1]}/${m[2]}` });
1404
+ }
1405
+ log(`# leerness skill discover (1.9.182 โ€” GitHub presets)`);
1406
+ if (query) log(`query: ${query}`);
1407
+ log(`targets: ${targets.map(t => `${t.owner}/${t.repo}#${t.branch}:${t.path}`).join(', ')}`);
1408
+ log('');
1409
+ const allEntries = [];
1410
+ for (const t of targets) {
1411
+ log(` fetching ${t.owner}/${t.repo}...`);
1412
+ const r = await _fetchGitHubSkills(t.owner, t.repo, t.branch, t.path);
1413
+ if (!r.ok) {
1414
+ log(` โš  ${t.owner}/${t.repo}: ${r.error}`);
1415
+ continue;
1416
+ }
1417
+ log(` โœ“ ${t.owner}/${t.repo}: ${r.skills.length}๊ฐœ skill ๋ฐœ๊ฒฌ`);
1418
+ for (const s of r.skills) allEntries.push(s);
1419
+ }
1420
+ log('');
1421
+ if (has('--json')) { log(JSON.stringify({ presets: targets.map(t => t.key), query, entries: allEntries }, null, 2)); return; }
1422
+ if (!allEntries.length) {
1423
+ log(' (์Šคํ‚ฌ 0๊ฑด โ€” preset/path/branch ํ™•์ธ ๋˜๋Š” rate limit ๊ฐ€๋Šฅ)');
1424
+ return;
1425
+ }
1426
+ let matched = allEntries;
1427
+ if (query) {
1428
+ const q = query.toLowerCase();
1429
+ matched = allEntries.filter(e => e.name.toLowerCase().includes(q) || (e.description || '').toLowerCase().includes(q));
1430
+ log(`๋งค์นญ ${matched.length}/${allEntries.length}๊ฑด (query: ${query})`);
1431
+ } else {
1432
+ log(`์ „์ฒด ${allEntries.length}๊ฑด (์ „์ฒด ํ‘œ์‹œ โ€” ๋งค์นญ ์—†์Œ)`);
1433
+ }
1434
+ log('');
1435
+ log('| name | source | url |');
1436
+ log('|---|---|---|');
1437
+ for (const e of matched.slice(0, 40)) {
1438
+ log(`| ${e.name} | ${e.source} | ${e.url} |`);
1439
+ }
1440
+ log('');
1441
+ log(`๐Ÿ’ก ์„ค์น˜: leerness skill install <url> ยท ์ž๋™ install (env opt-in): LEERNESS_SKILL_AUTO_INSTALL=1`);
1442
+ return;
1443
+ }
1444
+
1445
+ // ๊ธฐ์กด ๋‹จ์ผ URL ํ๋ฆ„ (1.9.42)
1446
+ const url = arg('--source', null) || process.env.LEERNESS_SKILL_DISCOVER_URL || null;
1329
1447
  if (!url) {
1330
1448
  fail([
1331
1449
  'LEERNESS_SKILL_DISCOVER_URL ํ™˜๊ฒฝ๋ณ€์ˆ˜ ๋˜๋Š” --source URL ํ•„์š”.',
1450
+ '',
1451
+ '๋˜๋Š” (1.9.182 ์‹ ๊ทœ) โ€” ๊ณต์‹ ์กฐ์ง catalog presets:',
1452
+ ' leerness skill discover --preset vercel # vercel-labs/agent-skills',
1453
+ ' leerness skill discover --preset anthropic # anthropics/skills',
1454
+ ' leerness skill discover --all-presets # ๋ชจ๋“  preset ๋™์‹œ ํƒ์ƒ‰',
1455
+ ' leerness skill discover --github owner/repo # ์ง์ ‘ GitHub repo ์ง€์ •',
1456
+ '',
1332
1457
  '์˜ˆ: leerness skill discover --source https://agentskills.io/llms.txt',
1333
- '๋˜๋Š” .env์— LEERNESS_SKILL_DISCOVER_URL=...',
1334
1458
  '',
1335
1459
  '(์ •์ฑ…: leerness๋Š” ์‚ฌ์šฉ์ž ๋™์˜ ์—†์ด ์™ธ๋ถ€ URL์„ fetchํ•˜์ง€ ์•Š์Œ โ€” 1.9.42 opt-in)'
1336
1460
  ].join('\n'));
@@ -1372,6 +1496,78 @@ async function skillDiscoverCmd(root) {
1372
1496
  log(`๐Ÿ’ก ์„ค์น˜: leerness skill install <url>`);
1373
1497
  }
1374
1498
 
1499
+ // 1.9.182: skill auto-install โ€” ๊ณต์‹ organization catalog ์ž๋™ ํƒ์ƒ‰ โ†’ skill match โ†’ ์ž๋™ install.
1500
+ // ์‚ฌ์šฉ์ž ๋ช…์‹œ: "์Šคํ‚ฌ์„ ์‚ฌ์šฉํ•˜๊ฑฐ๋‚˜ ์ ์šฉํ•ด๋‘๋ฉด ์ข‹์„ ๋ถ€๋ถ„๋“ค์„ ์•Œ์•„์„œ ์›น์—์„œ ๊ณต์‹ ์กฐ์ง์˜ ์Šคํ‚ฌ ๋ชจ์Œ์„ ํƒ์ƒ‰ํ•ด์„œ ๋‹ค์šด๋กœ๋“œ ๋ฐ›์•„์„œ ์‚ฌ์šฉ"
1501
+ // ์ •์ฑ…: LEERNESS_SKILL_AUTO_INSTALL=1 ์ผ ๋•Œ๋งŒ ์‹ค์ œ install (๋ณด์•ˆ opt-in). ๋ฏธ์„ค์ • ์‹œ dry-run (์ถ”์ฒœ๋งŒ).
1502
+ async function skillAutoInstallCmd(root) {
1503
+ root = absRoot(root);
1504
+ const presets = (process.env.LEERNESS_SKILL_AUTO_PRESETS || arg('--presets', 'vercel,anthropic') || '').split(',').map(s => s.trim()).filter(Boolean);
1505
+ const autoInstall = process.env.LEERNESS_SKILL_AUTO_INSTALL === '1' || has('--yes');
1506
+ const query = arg('--query', null) || _autoInstallQueryFromHandoff(root);
1507
+ const maxInstall = Number(arg('--max', '3'));
1508
+ log(`# leerness skill auto-install (1.9.182)`);
1509
+ log(`presets: ${presets.join(', ') || '(none)'}`);
1510
+ log(`query: ${query || '(auto โ€” handoff ์ปจํ…์ŠคํŠธ)'}`);
1511
+ log(`mode: ${autoInstall ? '๐ŸŸข ์ž๋™ install' : '๐ŸŸก dry-run (LEERNESS_SKILL_AUTO_INSTALL=1 ๋˜๋Š” --yes ํ•„์š”)'}`);
1512
+ log('');
1513
+ const allEntries = [];
1514
+ for (const key of presets) {
1515
+ const p = SKILL_CATALOG_PRESETS[key];
1516
+ if (!p) { log(` โš  ์•Œ ์ˆ˜ ์—†๋Š” preset: ${key}`); continue; }
1517
+ log(` fetching ${p.owner}/${p.repo}...`);
1518
+ const r = await _fetchGitHubSkills(p.owner, p.repo, p.branch, p.path);
1519
+ if (!r.ok) { log(` โš  ${p.owner}/${p.repo}: ${r.error}`); continue; }
1520
+ log(` โœ“ ${p.owner}/${p.repo}: ${r.skills.length}๊ฐœ skill`);
1521
+ for (const s of r.skills) allEntries.push(s);
1522
+ }
1523
+ log('');
1524
+ // query ๋งค์นญ (substring) โ€” query ์—†์œผ๋ฉด ๋ชจ๋“  ํ•ญ๋ชฉ
1525
+ let matched = allEntries;
1526
+ if (query) {
1527
+ const q = String(query).toLowerCase();
1528
+ matched = allEntries.filter(e => e.name.toLowerCase().includes(q) || (e.description || '').toLowerCase().includes(q));
1529
+ log(`๋งค์นญ ${matched.length}/${allEntries.length}๊ฑด (query: ${query})`);
1530
+ } else {
1531
+ log(`์ „์ฒด ${allEntries.length}๊ฑด (๋ชจ๋“  ํ•ญ๋ชฉ)`);
1532
+ }
1533
+ if (!matched.length) { log(' (๋งค์นญ 0๊ฑด โ€” query ๋ณ€๊ฒฝ ๋˜๋Š” --presets ์ถ”๊ฐ€)'); return; }
1534
+ log('');
1535
+ log('| name | source | url |');
1536
+ log('|---|---|---|');
1537
+ for (const e of matched.slice(0, maxInstall)) {
1538
+ log(`| ${e.name} | ${e.source} | ${e.url} |`);
1539
+ }
1540
+ log('');
1541
+ if (!autoInstall) {
1542
+ log(`๐Ÿ’ก ์ž๋™ install ํ™œ์„ฑํ™”: .env ์— LEERNESS_SKILL_AUTO_INSTALL=1 ๋˜๋Š” \`leerness skill auto-install --yes\``);
1543
+ log(` ํ˜„์žฌ ${Math.min(maxInstall, matched.length)}๊ฑด์ด install ๋Œ€์ƒ (์‹ค์ œ ๋‹ค์šด๋กœ๋“œ X โ€” dry-run)`);
1544
+ return;
1545
+ }
1546
+ log(`๐Ÿ“ฅ ์ž๋™ install ์‹œ์ž‘ โ€” ์ตœ๋Œ€ ${maxInstall}๊ฑด`);
1547
+ let installed = 0, failed = 0;
1548
+ for (const e of matched.slice(0, maxInstall)) {
1549
+ try {
1550
+ await skillInstallCmd(root, e.url);
1551
+ installed++;
1552
+ } catch (err) {
1553
+ log(` โš  ${e.name} install ์‹คํŒจ: ${err.message}`);
1554
+ failed++;
1555
+ }
1556
+ }
1557
+ log('');
1558
+ log(`โœ“ auto-install ์™„๋ฃŒ: ${installed}๊ฑด ์„ค์น˜ / ${failed}๊ฑด ์‹คํŒจ / ${matched.length - installed - failed}๊ฑด skip`);
1559
+ }
1560
+
1561
+ // 1.9.182: handoff ์ปจํ…์ŠคํŠธ (ํ˜„์žฌ in-progress task) ์—์„œ ์ž๋™ query ์ถ”์ถœ
1562
+ function _autoInstallQueryFromHandoff(root) {
1563
+ try {
1564
+ const rows = readProgressRows(root);
1565
+ const active = rows.find(r => r.status === '[์ง„ํ–‰]' || r.status === '[in-progress]' || r.status === 'in_progress');
1566
+ if (active) return (active.request || '').split(/\s+/).slice(0, 3).join(' ');
1567
+ } catch {}
1568
+ return null;
1569
+ }
1570
+
1375
1571
  // skill export <id> โ€” ๊ธฐ์กด ์ž์ฒด skill์„ agentskills.io ํ‘œ์ค€ SKILL.md๋กœ export
1376
1572
  function skillExportCmd(root, id) {
1377
1573
  if (!id) { fail('์‚ฌ์šฉ๋ฒ•: leerness skill export <id>'); return process.exit(1); }
@@ -4906,9 +5102,10 @@ async function _warnIfStale(root, opts = {}) {
4906
5102
  log(C.d(' npm registry latest: ') + C.b(`v${latest}`));
4907
5103
  log(C.d(' ์ด CLI๊ฐ€ ์‹คํ–‰ํ•œ ๋ฒ„์ „: ') + C.b(`v${VERSION}`) + C.d(' (npx ์บ์‹œ ๋˜๋Š” ๊ธ€๋กœ๋ฒŒ ์„ค์น˜ stale)'));
4908
5104
  log('');
4909
- log(C.d(' ํ•ด๊ฒฐ โ€” ๋‘˜ ์ค‘ ํ•˜๋‚˜ ์‹คํ–‰ ํ›„ ๋‹ค์‹œ ์‹œ๋„:'));
5105
+ log(C.d(' ํ•ด๊ฒฐ โ€” ์…‹ ์ค‘ ํ•˜๋‚˜ ์‹คํ–‰ ํ›„ ๋‹ค์‹œ ์‹œ๋„:'));
5106
+ log(' ' + C.b('npm i leerness@latest') + C.d(' # ํ”„๋กœ์ ํŠธ ๋กœ์ปฌ ์„ค์น˜ (1.9.183 ๊ถŒ์žฅ)'));
5107
+ log(' ' + C.b('npm i -g leerness@latest') + C.d(' # ๊ธ€๋กœ๋ฒŒ ์„ค์น˜'));
4910
5108
  log(' ' + C.b('npx --yes clear-npx-cache && npx leerness@latest init .'));
4911
- log(' ' + C.b('npm i -g leerness@latest โ†’ leerness init .'));
4912
5109
  log('');
4913
5110
  log(C.d(' (์ด ๊ฒฝ๊ณ ๋Š” LEERNESS_NO_STALE_CHECK=1 ๋˜๋Š” --no-stale-check๋กœ ๋Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค)'));
4914
5111
  log('');
@@ -13426,6 +13623,22 @@ async function main() {
13426
13623
  if (exists(path.join(root, '.harness'))) _bumpUsage(root, cmd);
13427
13624
  } catch {}
13428
13625
  }
13626
+ // 1.9.183 (์‚ฌ์šฉ์ž ๋ช…์‹œ): ๋ชจ๋“  ๋ช…๋ น ์‹œ์ ์—์„œ ๊ตฌ๋ฒ„์ „ ๊ฐ์ง€ + ๊ฒฝ๊ณ  + ์—…๋ฐ์ดํŠธ ๋ช…๋ น์–ด ์•ˆ๋‚ด.
13627
+ // init/migrate ๋Š” ์ด๋ฏธ _warnIfStale ํ˜ธ์ถœํ•˜๋ฏ€๋กœ ์ œ์™ธ. mcp/version/help ๋“ฑ ์ถœ๋ ฅ ๋ฏผ๊ฐ ๋ช…๋ น๋„ ์ œ์™ธ.
13628
+ // 24h ์บ์‹œ (.harness/cache/update-check.json) ํ™œ์šฉ โ€” ๋„คํŠธ์›Œํฌ ๋น„์ฐจ๋‹จ.
13629
+ const _staleSkip = new Set(['init', 'migrate', 'usage', 'mcp', 'release', 'session-close', '--version', '--help', 'help', 'update', 'whats-new']);
13630
+ if (!_staleSkip.has(cmd) && process.env.LEERNESS_NO_STALE_CHECK !== '1' && !has('--no-stale-check')) {
13631
+ try {
13632
+ const root = absRoot(arg('--path', args[1] && !args[1].startsWith('-') ? args[1] : process.cwd()));
13633
+ // ์บ์‹œ fresh ์‹œ์—๋งŒ ์ฆ‰์‹œ ๋น„๊ต (๋„คํŠธ์›Œํฌ ํ˜ธ์ถœ X โ€” ๋น„์ฐจ๋‹จ). offline + cache ์—†์œผ๋ฉด skip.
13634
+ const cached = readUpdateCache(root);
13635
+ if (cacheFresh(cached, 24) && cached.nextLeerness && compareVer(cached.nextLeerness, VERSION) > 0) {
13636
+ const isTty = process.stdout && process.stdout.isTTY;
13637
+ const C = isTty ? { y: s => `\x1b[33m${s}\x1b[0m`, b: s => `\x1b[1m${s}\x1b[0m`, d: s => `\x1b[2m${s}\x1b[0m` } : { y: s => s, b: s => s, d: s => s };
13638
+ process.stderr.write(C.y(' โš  ') + C.b(`leerness v${VERSION} โ†’ v${cached.nextLeerness} ์‚ฌ์šฉ ๊ฐ€๋Šฅ`) + C.d(` ยท ${C.b('npm i leerness@latest')} ๊ถŒ์žฅ (LEERNESS_NO_STALE_CHECK=1 ๋กœ ๋„๊ธฐ)`) + '\n');
13639
+ }
13640
+ } catch {}
13641
+ }
13429
13642
  if (cmd === 'init') return await install(args[1] || process.cwd(), { force:false, dry:false, migration:false });
13430
13643
  // 1.9.64: install <skill-id-or-url> ๋ณ„์นญ (= skill install). ์ž์ฃผ ์“ฐ๋Š” ๋ช…๋ น ๋‹จ์ถ•ํ˜•.
13431
13644
  // ๋‹จ, init์ด leerness install . ๊ฐ™์€ ํ˜•ํƒœ๋กœ๋„ ๋™์ž‘ํ•˜๋˜ ์˜› ํ˜ธํ™˜์€ ์œ ์ง€ โ€” args[1]์ด ๋””๋ ‰ํ† ๋ฆฌ๋ฉด init์œผ๋กœ ๋ผ์šฐํŒ….
@@ -13540,6 +13753,8 @@ async function main() {
13540
13753
  if (cmd === 'benchmark') return benchmarkCmd(absRoot(args[1] || arg('--path', process.cwd())));
13541
13754
  if (cmd === 'skill' && args[1] === 'publish') return skillPublishCmd(absRoot(arg('--path', process.cwd())));
13542
13755
  if (cmd === 'skill' && args[1] === 'suggest') return skillSuggestCmd(absRoot(arg('--path', process.cwd())));
13756
+ // 1.9.182: leerness skill auto-install โ€” ๊ณต์‹ catalog ์ž๋™ ํƒ์ƒ‰ + skill match ๋งค์นญ ์‹œ ์ž๋™ install (์‚ฌ์šฉ์ž ๋ช…์‹œ)
13757
+ if (cmd === 'skill' && args[1] === 'auto-install') return await skillAutoInstallCmd(absRoot(arg('--path', process.cwd())));
13543
13758
  if (cmd === 'mcp' && args[1] === 'serve') return mcpServeCmd(absRoot(arg('--path', process.cwd())));
13544
13759
  if (cmd === 'gate') return gate(args[1] || process.cwd());
13545
13760
  if (cmd === 'verify-code') return verifyCodeCmd(args[1] || process.cwd());
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "leerness",
3
- "version": "1.9.181",
3
+ "version": "1.9.183",
4
4
  "description": "Leerness: ๋น„ํŒŒ๊ดด ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜, ์ž๋™ ๋ฒ„์ „ ๊ฐ์ง€ยท์—…๋ฐ์ดํŠธ, ๊ณ„ํš/์ง„ํ–‰/ํ•ธ๋“œ์˜คํ”„ ์ž๋™ํ™”, ๊ฒŒ์œผ๋ฆ„ยท์‹œํฌ๋ฆฟยท์ธ์ฝ”๋”ฉ ์ž๋™ ๊ฐ€๋“œ, Claude Code ์Šฌ๋ž˜์‹œ ํ†ตํ•ฉ์„ ๊ฐ–์ถ˜ ํ•œ๊ตญ์–ด ์šฐ์„  AI ๊ฐœ๋ฐœ ํ•˜๋„ค์Šค.",
5
5
  "keywords": [
6
6
  "leerness",