leerness 1.9.183 β†’ 1.9.184

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,92 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.9.184 β€” 2026-05-21
4
+
5
+ **🎨 μ„€μΉ˜ UX 4μ’… β€” Ctrl+C 확인 prompt + λ‘œλ”©λ°” + skillpack μ œμ™Έ + DEP0190 μ–΅μ œ (μ‚¬μš©μž λͺ…μ‹œ).**
6
+
7
+ 자율 λͺ¨λ“œ 114 λΌμš΄λ“œ. μ‚¬μš©μž λͺ…μ‹œ 4μ’…:
8
+ 1. *"μ„€μΉ˜ κ°€μ΄λ“œμ—μ„œ Ctrl+C μž…λ ₯ μ‹œ μ„€μΉ˜ μ’…λ£Œ μ—¬λΆ€ 확인 둜직 μΆ”κ°€"* β†’ SIGINT handler (2단계 confirm)
9
+ 2. *"leerness 파일 μ„€μΉ˜ μ‹œμž‘ μ‹œ λ‘œλ”©λ°”λ‘œ κ΅¬ν˜„ + 생성 λͺ©λ‘ λ‚˜μ—΄ X"* β†’ progress bar (TTY)
10
+ 3. *"leerness-skillpack λ―Έμ‚¬μš© μ˜ˆμ • β†’ μ œμ™Έ"* β†’ μ•ˆλ‚΄ λ©”μ‹œμ§€ 제거
11
+ 4. *"REPL agent λͺ¨λ“œ μ§„μž… μ‹œ DEP0190 deprecation warning 제거"* β†’ process warning handler
12
+
13
+ ### Fix #1 β€” Ctrl+C μ’…λ£Œ 확인 prompt
14
+ ```js
15
+ // 1.9.184 (μ‚¬μš©μž λͺ…μ‹œ): μ„€μΉ˜ 도쀑 Ctrl+C μ‹œ μ’…λ£Œ 확인 prompt.
16
+ // 첫 Ctrl+C β†’ μ•ˆλ‚΄ (2초 이내 ν•œ 번 더 β†’ μ’…λ£Œ, κ·Έ μ™Έ β†’ 계속).
17
+ let _sigintCount = 0; let _sigintTimer = null;
18
+ const _sigintHandler = () => {
19
+ _sigintCount++;
20
+ if (_sigintCount === 1) {
21
+ process.stdout.write('\n\n ⚠ μ„€μΉ˜ μ€‘λ‹¨ν•˜μ‹œκ² μŠ΅λ‹ˆκΉŒ? Ctrl+C λ₯Ό 2초 이내에 ν•œ 번 더 λˆ„λ₯΄λ©΄ μ’…λ£Œλ©λ‹ˆλ‹€. (κ·Έ μ™Έ β†’ 계속 μ§„ν–‰)\n');
22
+ _sigintTimer = setTimeout(() => { _sigintCount = 0; }, 2000);
23
+ return;
24
+ }
25
+ process.exit(130);
26
+ };
27
+ ```
28
+ install μ‹œμž‘μ— 등둝, μ’…λ£Œ/REPL μ§„μž… μ‹œ cleanup.
29
+
30
+ ### Fix #2 β€” 파일 μ„€μΉ˜ progress bar (생성 λͺ©λ‘ λ―Έν‘œμ‹œ)
31
+ **Before** (line by line):
32
+ ```
33
+ βœ“ create: AGENTS.md
34
+ βœ“ create: CLAUDE.md
35
+ βœ“ create: .harness/HARNESS_VERSION
36
+ βœ“ create: .harness/manifest.json
37
+ ... (μˆ˜μ‹­ 쀄)
38
+ ```
39
+
40
+ **After** (single progress bar):
41
+ ```
42
+ β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–‘β–‘β–‘β–‘ 24/30 (80%) .harness/skills/office/SKILL.md
43
+ ```
44
+ μ™„λ£Œ μ‹œ:
45
+ ```
46
+ βœ“ leerness 파일 μ„€μΉ˜ μ™„λ£Œ (30개)
47
+ ```
48
+
49
+ ### Fix #3 β€” leerness-skillpack μ•ˆλ‚΄ 제거
50
+ ```diff
51
+ - if (SKILLPACK_SOURCE === 'builtin') log(`Skill catalog source: builtin (leerness-skillpack λ―Έμ„€μΉ˜ β€” npm i leerness-skillpack 둜 ν™•μž₯ κ°€λŠ₯)`);
52
+ - else log(`Skill catalog source: ${SKILLPACK_SOURCE} (leerness-skillpack${SKILLPACK_META ? ` v${SKILLPACK_META.version}` : ''})`);
53
+ + // 1.9.184 (μ‚¬μš©μž λͺ…μ‹œ): leerness-skillpack λ―Έμ‚¬μš© μ •μ±… β€” μ•ˆλ‚΄ λ©”μ‹œμ§€ 제거. builtin catalog 만 μ‚¬μš©.
54
+ ```
55
+
56
+ ### Fix #4 β€” DEP0190 DeprecationWarning μ–΅μ œ
57
+ 파일 μ΅œμƒλ‹¨μ—μ„œ process warning handler 등둝:
58
+ ```js
59
+ // 1.9.184: DEP0190 (child_process shell: true) deprecation warning μ–΅μ œ (μ‚¬μš©μž λͺ…μ‹œ).
60
+ // leerness λŠ” cross-platform PATH resolution 을 μœ„ν•΄ shell: true λ₯Ό μ˜λ„μ μœΌλ‘œ μ‚¬μš©.
61
+ process.removeAllListeners('warning');
62
+ process.on('warning', (w) => {
63
+ if (w && (w.code === 'DEP0190' || /DEP0190/.test(String(w.message || '')))) return;
64
+ process.stderr.write(`(node:${process.pid}) ${w.name || 'Warning'}: ${w.message || w}\n`);
65
+ });
66
+ ```
67
+
68
+ **Before** (REPL μ§„μž… μ‹œ):
69
+ ```
70
+ agent[claude/actor/β–Ά]> (node:54076) [DEP0190] DeprecationWarning: Passing args to a child process with shell option true...
71
+ ```
72
+
73
+ **After** (REPL μ§„μž… μ‹œ):
74
+ ```
75
+ agent[claude/actor/β–Ά]> _
76
+ ```
77
+ 깔끔.
78
+
79
+ ### Verified
80
+ - stress-v129: **14/14 PASS** (μ‚¬μš©μž λͺ…μ‹œ 4 + live install 3 + λˆ„μ  7)
81
+ - e2e 217/217 baseline μœ μ§€
82
+ - live install 검증:
83
+ - DEP0190 좜λ ₯ μ•ˆ 됨 βœ“
84
+ - "Skill catalog source: builtin" μ•ˆλ‚΄ μ—†μŒ βœ“
85
+ - 파일 생성 λͺ©λ‘ 0건 (non-TTY) βœ“
86
+ - VERSION = 1.9.184 Β· autonomous-rounds = 114 Β· main μžλ™ push 45 λΌμš΄λ“œ 연속
87
+
88
+ ---
89
+
3
90
  ## 1.9.183 β€” 2026-05-21
4
91
 
5
92
  **πŸ“¦ npm i leerness + ꡬ버전 μžλ™ 감지/κ²½κ³ /μ—…λ°μ΄νŠΈ λͺ…λ Ήμ–΄ μ•ˆλ‚΄ (μ‚¬μš©μž λͺ…μ‹œ 3μ’…).**
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.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)]()
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.184-green)]() [![tests](https://img.shields.io/badge/e2e-217%2F217-success)]() [![stress](https://img.shields.io/badge/stress--v129-14%2F14-success)]() [![mcp](https://img.shields.io/badge/MCP--tools-54-brightgreen)]() [![rounds](https://img.shields.io/badge/autonomous--rounds-114-blueviolet)]() [![main-push](https://img.shields.io/badge/release--main--push-45_rounds-success)]() [![install-ux](https://img.shields.io/badge/μ„€μΉ˜_UX-Ctrl%2BC확인%2Bλ‘œλ”©λ°”-success)]() [![dep-clean](https://img.shields.io/badge/DEP0190-μ–΅μ œ-success)]() [![install](https://img.shields.io/badge/npm_i_leerness-μ¦‰μ‹œ_μ‚¬μš©_κ°€λŠ₯-success)]() [![stale-check](https://img.shields.io/badge/ꡬ버전_감지-λͺ¨λ“ _λͺ…λ Ή-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.183 AI Agent Reliability Harness + Sandbox β•‘
15
+ β•‘ v1.9.184 AI Agent Reliability Harness + Sandbox β•‘
16
16
  β•‘ verify Β· remember Β· orchestrate Β· audit Β· sandbox Β· drift β•‘
17
- β•‘ 🌐 곡식 catalog μžλ™ 탐색 Β· μžκ°€ μ„±μž₯ν˜• Β· ꡬ버전 감지/μ•ˆλ‚΄ β•‘
17
+ β•‘ 🎨 μ„€μΉ˜ UX κ°œμ„  (λ‘œλ”©λ°”Β·Ctrl+C확인·DEP0190 μ–΅μ œΒ·κΉ¨λ—ν•œ REPL) β•‘
18
18
  β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•
19
19
  ```
20
20
 
package/bin/harness.js CHANGED
@@ -7,7 +7,17 @@ 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.183';
10
+ const VERSION = '1.9.184';
11
+
12
+ // 1.9.184: DEP0190 (child_process shell: true) deprecation warning μ–΅μ œ (μ‚¬μš©μž λͺ…μ‹œ).
13
+ // leerness λŠ” cross-platform PATH resolution 을 μœ„ν•΄ shell: true λ₯Ό μ˜λ„μ μœΌλ‘œ μ‚¬μš© (claude.cmd / ollama.cmd λ“± Windows .cmd 처리).
14
+ // 인자 escape κ°€ ν•„μš”ν•œ μœ„μΉ˜λŠ” κ²€μ¦λœ μž…λ ₯만 spawnSync 에 전달. REPL agent μ§„μž… μ‹œ _checkAgent κ°€ λ°œμ‚°ν•˜λŠ” λ…Έμ΄μ¦ˆ 제거.
15
+ process.removeAllListeners('warning');
16
+ process.on('warning', (w) => {
17
+ if (w && (w.code === 'DEP0190' || /DEP0190/.test(String(w.message || '')))) return;
18
+ process.stderr.write(`(node:${process.pid}) ${w.name || 'Warning'}: ${w.message || w}\n`);
19
+ });
20
+
11
21
  const MARK = '<!-- leerness:managed -->';
12
22
  const README_START = '<!-- leerness:project-readme:start -->';
13
23
  const README_END = '<!-- leerness:project-readme:end -->';
@@ -767,6 +777,26 @@ async function resolveInstallOptions(root, opts = {}) {
767
777
 
768
778
  async function install(root, opts = {}) {
769
779
  root = absRoot(root); mkdirp(root);
780
+ // 1.9.184 (μ‚¬μš©μž λͺ…μ‹œ): μ„€μΉ˜ 도쀑 Ctrl+C μ‹œ μ’…λ£Œ 확인 prompt.
781
+ // 첫 Ctrl+C β†’ μ•ˆλ‚΄ (2초 이내 ν•œ 번 더 β†’ μ’…λ£Œ, κ·Έ μ™Έ β†’ 계속).
782
+ // readline raw mode μ‹œ readline 이 'SIGINT' 이벀트둜 ν‘μˆ˜ν•  수 μžˆμ–΄ process-level + finally ν•΄μ œ.
783
+ let _sigintCount = 0; let _sigintTimer = null;
784
+ const _sigintHandler = () => {
785
+ _sigintCount++;
786
+ if (_sigintCount === 1) {
787
+ try { process.stdout.write('\n\n ⚠ μ„€μΉ˜ μ€‘λ‹¨ν•˜μ‹œκ² μŠ΅λ‹ˆκΉŒ? Ctrl+C λ₯Ό 2초 이내에 ν•œ 번 더 λˆ„λ₯΄λ©΄ μ’…λ£Œλ©λ‹ˆλ‹€. (κ·Έ μ™Έ β†’ 계속 μ§„ν–‰)\n'); } catch {}
788
+ clearTimeout(_sigintTimer);
789
+ _sigintTimer = setTimeout(() => { _sigintCount = 0; }, 2000);
790
+ return;
791
+ }
792
+ clearTimeout(_sigintTimer);
793
+ try { process.stdout.write('\n βœ— μ„€μΉ˜ 쀑단됨 (μ‚¬μš©μž μš”μ²­)\n'); } catch {}
794
+ process.exit(130);
795
+ };
796
+ if (!opts.migration && !opts.nonInteractive && process.stdin.isTTY) {
797
+ process.on('SIGINT', _sigintHandler);
798
+ }
799
+ const _cleanupSigint = () => { try { process.removeListener('SIGINT', _sigintHandler); clearTimeout(_sigintTimer); } catch {} };
770
800
  // 1.9.41: migrate 직전 이전 버전 캑처 β€” μ°¨λΆ„ μ•ˆλ‚΄μ— μ‚¬μš©
771
801
  try {
772
802
  const hv = path.join(root, '.harness', 'HARNESS_VERSION');
@@ -796,8 +826,7 @@ async function install(root, opts = {}) {
796
826
  if (resolved.startRepl) log(`REPL μžλ™ μ‹œμž‘: 예 (μ„€μΉ˜ μ™„λ£Œ ν›„ \`leerness agent\` μ§„μž…)`);
797
827
  if (resolved.permissionMode) log(`Agent κΆŒν•œ λͺ¨λ“œ: ${resolved.permissionMode} (1.9.174 β€” REPLμ—μ„œ \`:permissions extended|full\` 둜 μ¦‰μ‹œ λ³€κ²½ κ°€λŠ₯)`);
798
828
  // 1.9.10: μŠ€ν‚¬ μΉ΄νƒˆλ‘œκ·Έ 좜처 μ•ˆλ‚΄
799
- if (SKILLPACK_SOURCE === 'builtin') log(`Skill catalog source: builtin (leerness-skillpack λ―Έμ„€μΉ˜ β€” \`npm i leerness-skillpack\`둜 ν™•μž₯ κ°€λŠ₯)`);
800
- else log(`Skill catalog source: ${SKILLPACK_SOURCE} (leerness-skillpack${SKILLPACK_META ? ` v${SKILLPACK_META.version}` : ''})`);
829
+ // 1.9.184 (μ‚¬μš©μž λͺ…μ‹œ): leerness-skillpack λ―Έμ‚¬μš© μ •μ±… β€” μ•ˆλ‚΄ λ©”μ‹œμ§€ 제거. builtin catalog 만 μ‚¬μš©.
801
830
  const files = coreFiles(root, lang, skills);
802
831
  const backup = createBackup(root, opts.force ? 'force' : (opts.migration ? 'migration' : 'init'), files, opts.dry);
803
832
  if (opts.dry) {
@@ -816,7 +845,20 @@ async function install(root, opts = {}) {
816
845
  '.claude/commands/handoff.md','.claude/commands/session-close.md','.claude/commands/audit.md','.claude/commands/lazy-detect.md','.claude/commands/update.md',
817
846
  '.claude/skills/leerness.md'
818
847
  ]);
848
+ // 1.9.184 (μ‚¬μš©μž λͺ…μ‹œ): 파일 μ„€μΉ˜ β€” 생성 λͺ©λ‘ λ‚˜μ—΄ X, λ‘œλ”©λ°” + 단일 μ™„λ£Œ λ©”μ‹œμ§€.
819
849
  const actions = [];
850
+ const totalFiles = Object.keys(files).length;
851
+ const isTty = process.stdout.isTTY && !opts.dry;
852
+ const drawProgress = (done, file) => {
853
+ if (!isTty) return;
854
+ const pct = Math.round(done * 100 / totalFiles);
855
+ const filled = Math.floor(pct / 5);
856
+ const bar = '\x1b[36m' + 'β–ˆ'.repeat(filled) + '\x1b[2m' + 'β–‘'.repeat(20 - filled) + '\x1b[0m';
857
+ const truncFile = (file || '').length > 32 ? '...' + file.slice(-29) : (file || '');
858
+ process.stdout.write(`\r ${bar} \x1b[1m${done}/${totalFiles}\x1b[0m (${pct}%) \x1b[2m${truncFile}\x1b[0m\x1b[K`);
859
+ };
860
+ drawProgress(0, '');
861
+ let _done = 0;
820
862
  for (const [f, c] of Object.entries(files)) {
821
863
  const existsNow = exists(path.join(root, f));
822
864
  const mergeManaged = managedOverwrite.has(f);
@@ -828,7 +870,12 @@ async function install(root, opts = {}) {
828
870
  }
829
871
  const r = writeIfSafe(root, f, c, { force: opts.force, mergeManaged, archiveDir: backup.archiveDir });
830
872
  actions.push(r);
831
- ok(`${r.action}: ${r.file}`);
873
+ _done++;
874
+ drawProgress(_done, f);
875
+ }
876
+ if (isTty) {
877
+ process.stdout.write('\r\x1b[K'); // clear progress line
878
+ log(` \x1b[32mβœ“\x1b[0m leerness 파일 μ„€μΉ˜ μ™„λ£Œ (${totalFiles}개)`);
832
879
  }
833
880
  if (!opts.dry) {
834
881
  mergeLinesFile(path.join(root, '.gitignore'), [
@@ -943,11 +990,13 @@ async function install(root, opts = {}) {
943
990
  log('');
944
991
  log('πŸš€ μ„€μΉ˜ μ™„λ£Œ β€” REPL agent λͺ¨λ“œλ₯Ό μ‹œμž‘ν•©λ‹ˆλ‹€...');
945
992
  log('');
993
+ _cleanupSigint(); // 1.9.184: REPL μ§„μž… μ „ SIGINT handler ν•΄μ œ (readline 이 자체 처리)
946
994
  try {
947
995
  await _agentRepl(root, { role: 'actor' }); // provider λ―Έμ§€μ • β†’ _agentRepl 의 auto-select λ™μž‘ (1.9.181 fix)
948
996
  } catch (e) { warn('REPL μ§„μž… μ‹€νŒ¨: ' + e.message); }
949
997
  }
950
998
  }
999
+ _cleanupSigint(); // 1.9.184: install ν•¨μˆ˜ μ’…λ£Œ μ‹œ SIGINT handler ν•΄μ œ (λͺ¨λ“  μ’…λ£Œ 경둜)
951
1000
  }
952
1001
 
953
1002
  function installSkills(root, skills) { for (const name of skills) addSkill(root, name, true); }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "leerness",
3
- "version": "1.9.183",
3
+ "version": "1.9.184",
4
4
  "description": "Leerness: λΉ„νŒŒκ΄΄ λ§ˆμ΄κ·Έλ ˆμ΄μ…˜, μžλ™ 버전 κ°μ§€Β·μ—…λ°μ΄νŠΈ, κ³„νš/μ§„ν–‰/ν•Έλ“œμ˜€ν”„ μžλ™ν™”, κ²ŒμœΌλ¦„Β·μ‹œν¬λ¦ΏΒ·μΈμ½”λ”© μžλ™ κ°€λ“œ, Claude Code μŠ¬λž˜μ‹œ 톡합을 κ°–μΆ˜ ν•œκ΅­μ–΄ μš°μ„  AI 개발 ν•˜λ„€μŠ€.",
5
5
  "keywords": [
6
6
  "leerness",