leerness 1.9.205 β†’ 1.9.206

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.206 β€” 2026-05-22
4
+
5
+ **🌐 i18n MVP + UI/UX 헬퍼 (μ‚¬μš©μž λͺ…μ‹œ 2μ’…).**
6
+
7
+ ### μ‚¬μš©μž λͺ…μ‹œ
8
+ > 1. *"μ„€μΉ˜ κ°€μ΄λ“œμ—μ„œ μ–Έμ–΄ 선택에 따라 μ„€μΉ˜ κ°€μ΄λ“œ 및 REPL agent λͺ¨λ“œ λ“± μ„€μ •λœ μ–Έμ–΄λ‘œ ν‘œμ‹œλ˜μ–΄μ•Ό"*
9
+ > 2. *"μ„€μΉ˜ κ°€μ΄λ“œ 및 REPL agent λͺ¨λ“œ UI UXλ₯Ό κ°œμ„ ν•΄μ€˜, λͺ¨μ…˜μ΄λ‚˜, ν…μŠ€νŠΈ 좜λ ₯방식 λ“±λ“±"*
10
+
11
+ ### 1. i18n μ‹œμŠ€ν…œ MVP (10 핡심 keys)
12
+ - `STRINGS` table (ko/en) β€” install.lang.* / install.agents.* / repl.welcome.* / common.*
13
+ - `_currentLang(root)` β€” `LEERNESS_LANG` env β†’ `.harness/LANGUAGE` β†’ 'ko' fallback
14
+ - `_t(key, lang)` β€” i18n lookup helper
15
+
16
+ ### 2. μ˜μ–΄ 선택 μ‹œ 후속 prompt μžλ™ μ˜μ–΄ ν‘œμ‹œ
17
+ - μ–Έμ–΄ 선택 μžμ²΄λŠ” ν•œκ΅­μ–΄ (μ‚¬μš©μžκ°€ μ–Έμ–΄λ₯Ό λͺ¨λ₯΄λ―€λ‘œ)
18
+ - 'en' 선택 μ‹œ `process.env.LEERNESS_LANG = 'en'` μ¦‰μ‹œ μ„€μ • β†’ agents prompt λ“± μžλ™ μ˜μ–΄ λ³€ν™˜
19
+
20
+ ### 3. UI/UX 헬퍼 (`_typewrite`, `_ui`)
21
+ - `_typewrite(text, delayMs)` β€” opt-in via `LEERNESS_TYPEWRITER=1` (TTY 만)
22
+ - `_ui.bold/dim/cyan/green/yellow/hr` β€” 색상 + ꡬ뢄선 ν‘œμ€€ν™”
23
+ - λΉ„-TTY ν™˜κ²½ μžλ™ fallback (plain text)
24
+
25
+ ### 4. λˆ„μ  νšŒκ·€ (1.9.200~205) β€” λͺ¨λ‘ μœ μ§€
26
+
27
+ ### 5. stress-v151 β€” 16/16 PASS
28
+ - i18n (3) + UI helpers (1) + install λ‹€κ΅­μ–΄ 적용 (3) + μ„±λŠ₯ (2) + λˆ„μ  (7)
29
+ - μ„±λŠ₯: --version cold start avg **1049 ms** Β· MCP 54 도ꡬ **768 ms**
30
+
31
+ ### 6. MVP λ…ΈνŠΈ (ν™•μž₯ κ°€λŠ₯ 섀계)
32
+ - ν˜„μž¬: 10 핡심 keys (μ„€μΉ˜ κ°€μ΄λ“œ + REPL welcome + common)
33
+ - μΆ”ν›„: REPL agent λͺ¨λ“œ 전체 메뉴 / handoff / resume λ“± ν™•μž₯ κ°€λŠ₯ (점진적)
34
+
35
+ ### 7. μžλ™ release
36
+ - main μžλ™ push **68 λΌμš΄λ“œ 연속** (1.9.140~206)
37
+ - npm publish μžλ™ (1.9.178~)
38
+
39
+ ---
40
+
3
41
  ## 1.9.205 β€” 2026-05-22
4
42
 
5
43
  **⚑ ScheduleWakeup μ‚¬μš©μž μš”μ²­ μš°μ„  κ°±μ‹  (μ‚¬μš©μž λͺ…μ‹œ) β€” wakeup miss μ‹€μΈ‘ 후속.**
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.205-green)]() [![tests](https://img.shields.io/badge/e2e-217%2F217-success)]() [![stress](https://img.shields.io/badge/stress--v150-16%2F16-success)]() [![mcp](https://img.shields.io/badge/MCP--tools-54-brightgreen)]() [![rounds](https://img.shields.io/badge/autonomous--rounds-135-blueviolet)]() [![main-push](https://img.shields.io/badge/release--main--push-67_rounds-success)]() [![goal-matrix](https://img.shields.io/badge/λͺ©μ _맀트릭슀-98%2F100_(5μΆ•)-brightgreen)]() [![wakeup-track](https://img.shields.io/badge/wakeup-early%2Fmissed_감지-success)]() [![perf](https://img.shields.io/badge/cold_start-464ms-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.206-green)]() [![tests](https://img.shields.io/badge/e2e-217%2F217-success)]() [![stress](https://img.shields.io/badge/stress--v151-16%2F16-success)]() [![mcp](https://img.shields.io/badge/MCP--tools-54-brightgreen)]() [![rounds](https://img.shields.io/badge/autonomous--rounds-136-blueviolet)]() [![main-push](https://img.shields.io/badge/release--main--push-68_rounds-success)]() [![goal-matrix](https://img.shields.io/badge/λͺ©μ _맀트릭슀-98%2F100_(5μΆ•)-brightgreen)]() [![i18n](https://img.shields.io/badge/i18n-ko%2Fen_MVP-success)]() [![perf](https://img.shields.io/badge/cold_start-1049ms-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.205 AI Agent Reliability Harness + Sandbox β•‘
15
+ β•‘ v1.9.206 AI Agent Reliability Harness + Sandbox β•‘
16
16
  β•‘ verify Β· remember Β· orchestrate Β· audit Β· sandbox Β· drift β•‘
17
- β•‘ ⚑ wakeup early/missed 감지 + μžλ™ κ°±μ‹  κ°€μ΄λ“œ (μ‚¬μš©μž λͺ…μ‹œ) β•‘
17
+ β•‘ 🌐 i18n ko/en MVP Β· _typewrite/_ui UI/UX 헬퍼 (μ‚¬μš©μž λͺ…μ‹œ) β•‘
18
18
  β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•
19
19
  ```
20
20
 
@@ -530,7 +530,7 @@ MIT β€” Β© leerness contributors
530
530
  <!-- leerness:project-readme:start -->
531
531
  ## Leerness Project Harness
532
532
 
533
- 이 ν”„λ‘œμ νŠΈλŠ” Leerness v1.9.144 ν•˜λ„€μŠ€λ₯Ό μ‚¬μš©ν•©λ‹ˆλ‹€. AI μ—μ΄μ „νŠΈλŠ” μž‘μ—… μ „ `leerness handoff`둜 μ»¨ν…μŠ€νŠΈλ₯Ό μ μž¬ν•˜κ³ , μž‘μ—… ν›„ `leerness check`/`leerness audit`/`leerness session close`λ₯Ό μˆ˜ν–‰ν•΄μ•Ό ν•©λ‹ˆλ‹€.
533
+ 이 ν”„λ‘œμ νŠΈλŠ” Leerness v1.9.206 ν•˜λ„€μŠ€λ₯Ό μ‚¬μš©ν•©λ‹ˆλ‹€. AI μ—μ΄μ „νŠΈλŠ” μž‘μ—… μ „ `leerness handoff`둜 μ»¨ν…μŠ€νŠΈλ₯Ό μ μž¬ν•˜κ³ , μž‘μ—… ν›„ `leerness check`/`leerness audit`/`leerness session close`λ₯Ό μˆ˜ν–‰ν•΄μ•Ό ν•©λ‹ˆλ‹€.
534
534
 
535
535
  ### Core Commands
536
536
 
@@ -572,7 +572,7 @@ leerness memory restore decision <date|title>
572
572
 
573
573
  ### MCP server (μ™ΈλΆ€ AI 톡합)
574
574
 
575
- Leerness v1.9.144λŠ” stdio JSON-RPC MCP serverλ₯Ό λ‚΄μž₯ν•©λ‹ˆλ‹€ β€” Claude Code Β· Cursor Β· Codex CLI λ“± μ™ΈλΆ€ AI에 **42개 도ꡬ**λ₯Ό λ…ΈμΆœ:
575
+ Leerness v1.9.206λŠ” stdio JSON-RPC MCP serverλ₯Ό λ‚΄μž₯ν•©λ‹ˆλ‹€ β€” Claude Code Β· Cursor Β· Codex CLI λ“± μ™ΈλΆ€ AI에 **42개 도ꡬ**λ₯Ό λ…ΈμΆœ:
576
576
 
577
577
  ```jsonc
578
578
  // μΉ΄ν…Œκ³ λ¦¬λ³„
@@ -593,7 +593,7 @@ Leerness v1.9.144λŠ” stdio JSON-RPC MCP serverλ₯Ό λ‚΄μž₯ν•©λ‹ˆλ‹€ β€” Claude Cod
593
593
  `<<autonomous-loop-dynamic>>` μ‹ ν˜Έλ§Œ 보내면 AIκ°€:
594
594
  1) λ‹€μŒ λΌμš΄λ“œ 후보 μ„ μ • β†’ 2) μ½”λ“œ λ³€κ²½ β†’ 3) stress-v* μ‹ κ·œ μž‘μ„± + λˆ„μ  νšŒκ·€ β†’ 4) e2e 219/219 β†’ 5) npm pack + git tag + GitHub release β†’ 6) main μžλ™ push (1.9.140+) β†’ 7) session close β†’ 8) λ‹€μŒ λΌμš΄λ“œ μ˜ˆμ•½.
595
595
 
596
- ν˜„μž¬ λˆ„μ : **70 λΌμš΄λ“œ (1.9.40 β†’ 1.9.144)** Β· λ§€ λΌμš΄λ“œ GitHub release/νƒœκ·Έ 생성 Β· _reports/λŠ” λΉ„κ³΅κ°œ 보쑴.
596
+ ν˜„μž¬ λˆ„μ : **70 λΌμš΄λ“œ (1.9.40 β†’ 1.9.206)** Β· λ§€ λΌμš΄λ“œ GitHub release/νƒœκ·Έ 생성 Β· _reports/λŠ” λΉ„κ³΅κ°œ 보쑴.
597
597
 
598
598
  ### μ„±λŠ₯ κ°€μ΄λ“œ (1.9.140 μΈ‘μ •)
599
599
 
@@ -631,6 +631,6 @@ leerness release pack --close --auto-main-push
631
631
  - `.harness/session-handoff.md`: λ‹€μŒ μ„Έμ…˜ μΈμˆ˜μΈκ³„ (μžλ™ μž‘μ„±)
632
632
  - `.harness/lessons.md` / `decisions.md` / `rules.md`: 영ꡬ λ©”λͺ¨λ¦¬ (5 surface)
633
633
 
634
- Last synced by Leerness v1.9.144: 2026-05-20
634
+ Last synced by Leerness v1.9.206: 2026-05-22
635
635
  <!-- leerness:project-readme:end -->
636
636
 
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.205';
10
+ const VERSION = '1.9.206';
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 처리).
@@ -766,19 +766,24 @@ async function resolveInstallOptions(root, opts = {}) {
766
766
  // --no-interactive-select λ˜λŠ” LEERNESS_NO_INTERACTIVE=1 β†’ ꡬ식 숫자 선택
767
767
  const useInteractive = shouldAsk && !has('--no-interactive-select') && process.env.LEERNESS_NO_INTERACTIVE !== '1';
768
768
  if (shouldAsk && !explicitLang) {
769
+ // 1.9.206: μ–Έμ–΄ 선택 μžμ²΄λŠ” 항상 ko (μ‚¬μš©μžκ°€ μ–Έμ–΄λ₯Ό λͺ¨λ₯΄λ―€λ‘œ) β†’ 선택 ν›„ 후속은 μ„ νƒλœ μ–Έμ–΄
769
770
  if (useInteractive) {
770
- const langOpt = await _selectOne('μ„€μΉ˜ μ–Έμ–΄λ₯Ό μ„ νƒν•˜μ„Έμš”', [
771
- { label: 'μžλ™ 감지', description: '디렉토리/파일 뢄석 (ν•œκ΅­μ–΄/μ˜μ–΄ μžλ™ νŒλ³„)', id: 'auto' },
772
- { label: 'ν•œκ΅­μ–΄', description: 'λͺ¨λ“  μΈμŠ€νŠΈλŸ­μ…˜μ„ ν•œκ΅­μ–΄λ‘œ 생성', id: 'ko' },
773
- { label: 'English', description: 'λͺ¨λ“  μΈμŠ€νŠΈλŸ­μ…˜μ„ μ˜μ–΄λ‘œ 생성', id: 'en' }
771
+ const langOpt = await _selectOne(_t('install.lang.title', 'ko'), [
772
+ { label: _t('install.lang.auto', 'ko'), description: _t('install.lang.auto.desc', 'ko'), id: 'auto' },
773
+ { label: _t('install.lang.ko', 'ko'), description: _t('install.lang.ko.desc', 'ko'), id: 'ko' },
774
+ { label: _t('install.lang.en', 'ko'), description: _t('install.lang.en.desc', 'ko'), id: 'en' }
774
775
  ], { defaultIndex: 0 });
775
776
  lang = langOpt && langOpt.id ? detectLanguageValue(root, langOpt.id) : detectLanguageValue(root, 'auto');
776
777
  } else {
777
- log('\nμ„€μΉ˜ μ–Έμ–΄λ₯Ό μ„ νƒν•˜μ„Έμš”.');
778
- log('1) μžλ™ 감지'); log('2) ν•œκ΅­μ–΄'); log('3) English');
779
- const a = await ask('선택 [1]: ');
778
+ log('\n' + _t('install.lang.title', 'ko') + '.');
779
+ log('1) ' + _t('install.lang.auto', 'ko'));
780
+ log('2) ' + _t('install.lang.ko', 'ko'));
781
+ log('3) ' + _t('install.lang.en', 'ko'));
782
+ const a = await ask('Select / 선택 [1]: ');
780
783
  lang = a === '2' ? 'ko' : a === '3' ? 'en' : detectLanguageValue(root, 'auto');
781
784
  }
785
+ // 1.9.206: μ˜μ–΄ 선택 μ‹œ 후속 prompt μ˜μ–΄ ν‘œμ‹œ ν™˜κ²½λ³€μˆ˜ μ¦‰μ‹œ μ„€μ •
786
+ if (lang === 'en') process.env.LEERNESS_LANG = 'en';
782
787
  }
783
788
  // 1.9.148: μŠ€ν‚¬ prompt 제거 (μ‚¬μš©μž λͺ…μ‹œ μš”μ²­) β€” leernessκ°€ μžλ™μœΌλ‘œ 곡식 ν‘œμ€€ μŠ€ν‚¬ 5μ’… μ„€μΉ˜.
784
789
  // ν•„μš”ν•  λ•Œ μ‚¬μš©μžκ°€ leerness skill install <id> 둜 μΆ”κ°€ κ°€λŠ₯.
@@ -787,8 +792,10 @@ async function resolveInstallOptions(root, opts = {}) {
787
792
  // _selectMany 둜 Space ν† κΈ€, a 전체, n ν•΄μ œ, Enter ν™•μ •. μ„ νƒλœ μ—μ΄μ „νŠΈλ“€λ§Œ .env.example에 LEERNESS_ENABLE_* ν™œμ„±ν™”.
788
793
  let agentsOptIn = null; // string[] (닀쀑) λ˜λŠ” 'none' (선택 μ•ˆν•¨)
789
794
  if (shouldAsk && !opts._skipAgentsPrompt) {
795
+ // 1.9.206: μ„ νƒλœ μ–Έμ–΄λ‘œ prompt ν‘œμ‹œ
796
+ const _agLang = lang === 'en' ? 'en' : 'ko';
790
797
  if (useInteractive) {
791
- const picked = await _selectMany('CLI μ—μ΄μ „νŠΈ ν™œμ„±ν™” (볡수 선택, Space ν† κΈ€) β€” sub-agent μœ„μž„μš©', [
798
+ const picked = await _selectMany(_t('install.agents.title', _agLang), [
792
799
  { label: 'Claude (ANTHROPIC_API_KEY λ˜λŠ” claude CLI)', description: 'μΆ”λ‘ λ ₯ 졜고 β€” μ½”λ“œ μž‘μ„±/리뷰 κΈ°λ³Έ', id: 'claude' },
793
800
  { label: 'Codex (OpenAI codex CLI)', description: 'OpenAI μ½”λ“œ λͺ¨λΈ', id: 'codex' },
794
801
  { label: 'Gemini (gemini CLI)', description: 'Google λ©€ν‹°λͺ¨λ‹¬ λͺ¨λΈ', id: 'gemini' },
@@ -1779,6 +1786,84 @@ async function skillAutoCacheCmd(root, sub) {
1779
1786
  if (c.expired) log(` β†’ κ°±μ‹ : leerness skill auto-cache refresh`);
1780
1787
  }
1781
1788
 
1789
+ // 1.9.206: i18n μ‹œμŠ€ν…œ (μ‚¬μš©μž λͺ…μ‹œ) β€” μ„€μΉ˜ κ°€μ΄λ“œ / REPL agent λ‹€κ΅­μ–΄ + UI/UX κ°œμ„ 
1790
+ // μ‚¬μš©μž λͺ…μ‹œ: "μ„€μΉ˜ κ°€μ΄λ“œμ—μ„œ μ–Έμ–΄ 선택에 따라 μ„€μΉ˜ κ°€μ΄λ“œ 및 REPL agent λͺ¨λ“œ λ“± μ„€μ •λœ μ–Έμ–΄λ‘œ ν‘œμ‹œ"
1791
+ // 섀계: 핡심 string table (ko/en) + _t(key, lang) helper. μ„€μΉ˜ μ‹œ 선택 μ–Έμ–΄ β†’ .harness/LANGUAGE μ €μž₯.
1792
+ // lang κ²°μ •: explicit > .harness/LANGUAGE > LEERNESS_LANG env > 'ko' (default)
1793
+ const STRINGS = {
1794
+ // μ„€μΉ˜ κ°€μ΄λ“œ prompt
1795
+ 'install.lang.title': { ko: 'μ„€μΉ˜ μ–Έμ–΄λ₯Ό μ„ νƒν•˜μ„Έμš”', en: 'Select install language' },
1796
+ 'install.lang.auto': { ko: 'μžλ™ 감지', en: 'Auto detect' },
1797
+ 'install.lang.auto.desc': { ko: '디렉토리/파일 뢄석 (ν•œκ΅­μ–΄/μ˜μ–΄ μžλ™ νŒλ³„)', en: 'Analyze dir/files (auto KO/EN)' },
1798
+ 'install.lang.ko': { ko: 'ν•œκ΅­μ–΄', en: 'Korean' },
1799
+ 'install.lang.ko.desc': { ko: 'λͺ¨λ“  μΈμŠ€νŠΈλŸ­μ…˜μ„ ν•œκ΅­μ–΄λ‘œ 생성', en: 'All instructions in Korean' },
1800
+ 'install.lang.en': { ko: 'English', en: 'English' },
1801
+ 'install.lang.en.desc': { ko: 'λͺ¨λ“  μΈμŠ€νŠΈλŸ­μ…˜μ„ μ˜μ–΄λ‘œ 생성', en: 'All instructions in English' },
1802
+ 'install.agents.title': { ko: 'CLI μ—μ΄μ „νŠΈ ν™œμ„±ν™” (볡수 선택, Space ν† κΈ€) β€” sub-agent μœ„μž„μš©',
1803
+ en: 'Enable CLI agents (multi-select, Space toggle) β€” for sub-agent dispatch' },
1804
+ 'install.agents.none': { ko: '선택 μ•ˆν•¨ (λ‚˜μ€‘μ— setup-agents)', en: 'None (later setup-agents)' },
1805
+ 'install.complete': { ko: 'βœ“ μ„€μΉ˜ μ™„λ£Œ', en: 'βœ“ Install complete' },
1806
+ // REPL agent λͺ¨λ“œ
1807
+ 'repl.welcome.title': { ko: 'leerness REPL agent', en: 'leerness REPL agent' },
1808
+ 'repl.welcome.subtitle': { ko: 'Tab provider Β· Shift+Tab model Β· :help Β· /slash', en: 'Tab provider Β· Shift+Tab model Β· :help Β· /slash' },
1809
+ 'repl.welcome.start': { ko: 'μ‹œμž‘ν•˜λ €λ©΄ λ©”μ‹œμ§€λ₯Ό μž…λ ₯ν•˜μ„Έμš”', en: 'Type a message to start' },
1810
+ // 곡톡
1811
+ 'common.cancel': { ko: 'μ·¨μ†Œλ¨', en: 'Cancelled' },
1812
+ 'common.confirm': { ko: '확인', en: 'Confirm' },
1813
+ 'common.ready': { ko: 'μ€€λΉ„ μ™„λ£Œ', en: 'Ready' }
1814
+ };
1815
+ // ν˜„μž¬ μ‚¬μš© μ–Έμ–΄ κ²°μ • (env > config > 'ko')
1816
+ function _currentLang(root) {
1817
+ if (process.env.LEERNESS_LANG) return process.env.LEERNESS_LANG === 'en' ? 'en' : 'ko';
1818
+ try {
1819
+ if (root) {
1820
+ const fp = path.join(root, '.harness', 'LANGUAGE');
1821
+ if (exists(fp)) {
1822
+ const v = read(fp).trim().toLowerCase();
1823
+ if (v === 'en' || v === 'english') return 'en';
1824
+ if (v === 'ko' || v === 'korean' || v === 'kr') return 'ko';
1825
+ }
1826
+ }
1827
+ } catch {}
1828
+ return 'ko'; // default
1829
+ }
1830
+ function _t(key, lang) {
1831
+ const entry = STRINGS[key];
1832
+ if (!entry) return key; // fallback: ν‚€ 자체 λ°˜ν™˜
1833
+ return entry[lang || 'ko'] || entry.ko || key;
1834
+ }
1835
+
1836
+ // 1.9.206: UI/UX κ°œμ„  β€” typewriter / fade-in 효과 (opt-in via LEERNESS_TYPEWRITER=1)
1837
+ function _typewrite(text, delayMs) {
1838
+ delayMs = delayMs || 15;
1839
+ if (process.env.LEERNESS_TYPEWRITER !== '1' || !process.stdout.isTTY) {
1840
+ process.stdout.write(text);
1841
+ return Promise.resolve();
1842
+ }
1843
+ return new Promise((resolve) => {
1844
+ let i = 0;
1845
+ const step = () => {
1846
+ if (i >= text.length) return resolve();
1847
+ process.stdout.write(text[i++]);
1848
+ setTimeout(step, delayMs);
1849
+ };
1850
+ step();
1851
+ });
1852
+ }
1853
+ // 색상 helper (TTY μ‹œ ANSI, λΉ„-TTY μ‹œ plain)
1854
+ const _ui = {
1855
+ bold: s => process.stdout.isTTY ? `\x1b[1m${s}\x1b[0m` : s,
1856
+ dim: s => process.stdout.isTTY ? `\x1b[2m${s}\x1b[0m` : s,
1857
+ cyan: s => process.stdout.isTTY ? `\x1b[36m${s}\x1b[0m` : s,
1858
+ green: s => process.stdout.isTTY ? `\x1b[32m${s}\x1b[0m` : s,
1859
+ yellow: s => process.stdout.isTTY ? `\x1b[33m${s}\x1b[0m` : s,
1860
+ // ꡬ뢄선 μ •λ ¬ (터미널 width κ³ λ €)
1861
+ hr: (char) => {
1862
+ const w = process.stdout.columns || 60;
1863
+ return (char || '─').repeat(Math.min(w - 2, 60));
1864
+ }
1865
+ };
1866
+
1782
1867
  // 1.9.205: ScheduleWakeup 등둝 좔적 (μ‚¬μš©μž λͺ…μ‹œ)
1783
1868
  // "μ˜ˆμ •λœ μ•ŒλžŒμ΄μ „μ— μ‚¬μš©μž μš”μ²­μ΄ λ“€μ–΄μ˜€λ©΄ λ°±κ·ΈλΌμš΄λ“œμ˜ μ•ŒλžŒμ„ μ’…λ£Œν›„ λ‹€μ‹œ κ°±μ‹ "
1784
1869
  // λΌμš΄λ“œ 마무리 μ‹œ λ“±λ‘λœ wakeup id/expectedFireAt 을 .harness/active-wakeups.json 에 기둝 β†’
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "leerness",
3
- "version": "1.9.205",
3
+ "version": "1.9.206",
4
4
  "description": "Leerness: λΉ„νŒŒκ΄΄ λ§ˆμ΄κ·Έλ ˆμ΄μ…˜, μžλ™ 버전 κ°μ§€Β·μ—…λ°μ΄νŠΈ, κ³„νš/μ§„ν–‰/ν•Έλ“œμ˜€ν”„ μžλ™ν™”, κ²ŒμœΌλ¦„Β·μ‹œν¬λ¦ΏΒ·μΈμ½”λ”© μžλ™ κ°€λ“œ, Claude Code μŠ¬λž˜μ‹œ 톡합을 κ°–μΆ˜ ν•œκ΅­μ–΄ μš°μ„  AI 개발 ν•˜λ„€μŠ€.",
5
5
  "keywords": [
6
6
  "leerness",