leerness 1.9.205 β 1.9.207
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 +83 -0
- package/README.md +7 -7
- package/bin/harness.js +310 -10
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,88 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.9.207 β 2026-05-22
|
|
4
|
+
|
|
5
|
+
**π₯ μ¬μ©μ μμ² λλ½ νμΈ μ μ°¨ MVP (μ¬μ©μ λͺ
μ).**
|
|
6
|
+
|
|
7
|
+
### μ¬μ©μ λͺ
μ
|
|
8
|
+
> *"leernessκ° μ μ©λ νλ‘μ νΈμμ, μ΅κ·Όμ λͺ
λ Ήλ°μ μ§νν κ²μ€μ λλ½λκ² μλμ§ νμΈνλ μ μ°¨λ μλμ§ νμΈν΄μ€ / λ€μ λΌμ΄λμ μ°Έμ‘°"*
|
|
9
|
+
|
|
10
|
+
### 1. `.harness/user-requests.json` β μ¬μ©μ μμ² λμ κΈ°λ‘
|
|
11
|
+
- `_userRequestsPath/_loadUserRequests/_writeUserRequests` νμΌ I/O ν¬νΌ
|
|
12
|
+
- `_recordUserRequest(root, text, opts)` β μλ ID λΆμ¬(UR-XXXX) + μ€λ³΅ λ°©μ§(λμΌ ν
μ€νΈ + open μν)
|
|
13
|
+
- `_updateUserRequest(root, id, patch)` β status μ ν (open β in-progress β completed/dropped)
|
|
14
|
+
- μ΅κ·Ό 200κ° μ μ§ (rotate)
|
|
15
|
+
|
|
16
|
+
### 2. `_auditUserRequests(root)` β λλ½ ν보 νμ§
|
|
17
|
+
- open/in-progress μμ² ν
μ€νΈμ 첫 12 λ¨μ΄ μΆμΆ β task-log/plan/decisions μ λΉκ΅
|
|
18
|
+
- hits β₯ min(3, wordsΓ0.5) β **tracked** (μ΄λκ° μμ
μ΄ μμλ¨)
|
|
19
|
+
- κ·Έ μΈ β **missing** (λλ½ ν보, AI/μ¬μ©μκ° μμ κ°λ₯μ±)
|
|
20
|
+
- 7μΌ+ open β **stale** (μ¬κ²ν νμ)
|
|
21
|
+
|
|
22
|
+
### 3. `leerness requests <sub>` CLI (μ¬μ©μ λͺ
μ β "νμΈ μ μ°¨")
|
|
23
|
+
- `audit` β missing/tracked/stale λ³΄κ³ (--json κ°λ₯)
|
|
24
|
+
- `add "<text>"` β μ¬μ©μ μμ² μλ κΈ°λ‘
|
|
25
|
+
- `list [--status open|completed|dropped]` β μ 체 μΆλ ₯
|
|
26
|
+
- `complete <UR-id>` / `drop <UR-id>` β μν μ ν
|
|
27
|
+
|
|
28
|
+
### 4. handoff ν€λλΌμΈ ν΅ν© (13λ²μ§Έ μμ)
|
|
29
|
+
- missing β₯ 1 μ: `π₯ λ―Έλ΅ μμ² N건` (red)
|
|
30
|
+
- open > 0 (λͺ¨λ tracked) μ: `π₯ μμ² N (tracked)` (green)
|
|
31
|
+
- ν€λλΌμΈ λΌλ²¨: `1.9.81/93/113/152/162/192/197/204/207`
|
|
32
|
+
|
|
33
|
+
### 5. λμ νκ· (1.9.200~206) β λͺ¨λ μ μ§
|
|
34
|
+
|
|
35
|
+
### 6. stress-v152 β 17/17 PASS
|
|
36
|
+
- 1.9.207 (8) + μ±λ₯ (2) + λμ νκ· (7)
|
|
37
|
+
- μ¬μ©μ μμ² λΌμ΄νμ¬μ΄ν΄ 격리 tmpdir ν
μ€νΈ (add β list β audit β complete β drop)
|
|
38
|
+
- μ€λ³΅ λ°©μ§ νμΈ
|
|
39
|
+
- μ±λ₯: --version cold start avg 2206ms Β· MCP 54 λꡬ 1597ms
|
|
40
|
+
|
|
41
|
+
### 7. μλ release (69 λΌμ΄λ main-push streak Β· 30 λΌμ΄λ npm publish streak)
|
|
42
|
+
- `release sync-main` μλ β main merge + npm publish leerness@1.9.207
|
|
43
|
+
- 1.9.140λΆν° main μλ push (69 λΌμ΄λ 무μ€λ¨)
|
|
44
|
+
- 1.9.178λΆν° npm publish (30 λΌμ΄λ 무μ€λ¨)
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## 1.9.206 β 2026-05-22
|
|
49
|
+
|
|
50
|
+
**π i18n MVP + UI/UX ν¬νΌ (μ¬μ©μ λͺ
μ 2μ’
).**
|
|
51
|
+
|
|
52
|
+
### μ¬μ©μ λͺ
μ
|
|
53
|
+
> 1. *"μ€μΉ κ°μ΄λμμ μΈμ΄ μ νμ λ°λΌ μ€μΉ κ°μ΄λ λ° REPL agent λͺ¨λ λ± μ€μ λ μΈμ΄λ‘ νμλμ΄μΌ"*
|
|
54
|
+
> 2. *"μ€μΉ κ°μ΄λ λ° REPL agent λͺ¨λ UI UXλ₯Ό κ°μ ν΄μ€, λͺ¨μ
μ΄λ, ν
μ€νΈ μΆλ ₯λ°©μ λ±λ±"*
|
|
55
|
+
|
|
56
|
+
### 1. i18n μμ€ν
MVP (10 ν΅μ¬ keys)
|
|
57
|
+
- `STRINGS` table (ko/en) β install.lang.* / install.agents.* / repl.welcome.* / common.*
|
|
58
|
+
- `_currentLang(root)` β `LEERNESS_LANG` env β `.harness/LANGUAGE` β 'ko' fallback
|
|
59
|
+
- `_t(key, lang)` β i18n lookup helper
|
|
60
|
+
|
|
61
|
+
### 2. μμ΄ μ ν μ νμ prompt μλ μμ΄ νμ
|
|
62
|
+
- μΈμ΄ μ ν μ체λ νκ΅μ΄ (μ¬μ©μκ° μΈμ΄λ₯Ό λͺ¨λ₯΄λ―λ‘)
|
|
63
|
+
- 'en' μ ν μ `process.env.LEERNESS_LANG = 'en'` μ¦μ μ€μ β agents prompt λ± μλ μμ΄ λ³ν
|
|
64
|
+
|
|
65
|
+
### 3. UI/UX ν¬νΌ (`_typewrite`, `_ui`)
|
|
66
|
+
- `_typewrite(text, delayMs)` β opt-in via `LEERNESS_TYPEWRITER=1` (TTY λ§)
|
|
67
|
+
- `_ui.bold/dim/cyan/green/yellow/hr` β μμ + ꡬλΆμ νμ€ν
|
|
68
|
+
- λΉ-TTY νκ²½ μλ fallback (plain text)
|
|
69
|
+
|
|
70
|
+
### 4. λμ νκ· (1.9.200~205) β λͺ¨λ μ μ§
|
|
71
|
+
|
|
72
|
+
### 5. stress-v151 β 16/16 PASS
|
|
73
|
+
- i18n (3) + UI helpers (1) + install λ€κ΅μ΄ μ μ© (3) + μ±λ₯ (2) + λμ (7)
|
|
74
|
+
- μ±λ₯: --version cold start avg **1049 ms** Β· MCP 54 λꡬ **768 ms**
|
|
75
|
+
|
|
76
|
+
### 6. MVP λ
ΈνΈ (νμ₯ κ°λ₯ μ€κ³)
|
|
77
|
+
- νμ¬: 10 ν΅μ¬ keys (μ€μΉ κ°μ΄λ + REPL welcome + common)
|
|
78
|
+
- μΆν: REPL agent λͺ¨λ μ 체 λ©λ΄ / handoff / resume λ± νμ₯ κ°λ₯ (μ μ§μ )
|
|
79
|
+
|
|
80
|
+
### 7. μλ release
|
|
81
|
+
- main μλ push **68 λΌμ΄λ μ°μ** (1.9.140~206)
|
|
82
|
+
- npm publish μλ (1.9.178~)
|
|
83
|
+
|
|
84
|
+
---
|
|
85
|
+
|
|
3
86
|
## 1.9.205 β 2026-05-22
|
|
4
87
|
|
|
5
88
|
**β‘ ScheduleWakeup μ¬μ©μ μμ² μ°μ κ°±μ (μ¬μ©μ λͺ
μ) β wakeup miss μ€μΈ‘ νμ.**
|
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
> **AI μ½λ© μμ΄μ νΈμ κ±°μ§ μλ£Β·μ€λ³΅Β·λ§κ°Β·μΆ©λμ λ§μμ£Όλ κ²μΒ·κΈ°μ΅Β·νμ
CLI νλ€μ€.**
|
|
4
4
|
|
|
5
|
-
[](https://www.npmjs.com/package/leerness) [](https://www.npmjs.com/package/leerness) []() []() []() []() []() []() [-brightgreen)]() []() []() []() []() []()
|
|
6
6
|
|
|
7
7
|
```
|
|
8
8
|
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
@@ -12,9 +12,9 @@
|
|
|
12
12
|
β βββ ββββββ ββββββ ββββββββββββββββββββββββ ββββββββ β
|
|
13
13
|
β βββββββββββββββββββββββββββ ββββββ ββββββββββββββββββββββ β
|
|
14
14
|
β βββββββββββββββββββββββββββ ββββββ βββββββββββββββββββββ β
|
|
15
|
-
β v1.9.
|
|
15
|
+
β v1.9.207 AI Agent Reliability Harness + Sandbox β
|
|
16
16
|
β verify Β· remember Β· orchestrate Β· audit Β· sandbox Β· drift β
|
|
17
|
-
β
|
|
17
|
+
β π₯ μ¬μ©μ μμ² λλ½ νμΈ (requests audit) (μ¬μ©μ λͺ
μ) β
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
10
|
+
const VERSION = '1.9.207';
|
|
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: '
|
|
772
|
-
{ label: '
|
|
773
|
-
{ label: '
|
|
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)
|
|
779
|
-
|
|
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('
|
|
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 μ κΈ°λ‘ β
|
|
@@ -1833,6 +1918,94 @@ function _analyzeWakeupStatus(root) {
|
|
|
1833
1918
|
return { hasWakeup: true, latest, deltaMin, kind, pending: pending.length };
|
|
1834
1919
|
}
|
|
1835
1920
|
|
|
1921
|
+
// 1.9.207: μ¬μ©μ μμ² λλ½ νμΈ μ μ°¨ β μ¬μ©μ λͺ
μ
|
|
1922
|
+
// "μ΅κ·Όμ λͺ
λ Ήλ°μ μ§νν κ²μ€μ λλ½λκ² μλμ§ νμΈνλ μ μ°¨λ μλμ§"
|
|
1923
|
+
// .harness/user-requests.json μ μ¬μ©μ λͺ
μ μμ²μ λμ κΈ°λ‘ β audit μ task-log/plan/decisions μ λ§€μΉ β λλ½ λ³΄κ³
|
|
1924
|
+
// λ μ½λ ꡬ쑰: { id, text, recordedAt, status: 'open'|'in-progress'|'completed'|'dropped',
|
|
1925
|
+
// linkedTaskIds?, linkedPlanIds?, linkedDecisionIds?, notes?, completedAt?, droppedAt? }
|
|
1926
|
+
function _userRequestsPath(root) { return path.join(root, '.harness', 'user-requests.json'); }
|
|
1927
|
+
function _loadUserRequests(root) {
|
|
1928
|
+
try {
|
|
1929
|
+
const fp = _userRequestsPath(root);
|
|
1930
|
+
if (!exists(fp)) return { requests: [] };
|
|
1931
|
+
const j = JSON.parse(read(fp));
|
|
1932
|
+
return { requests: Array.isArray(j.requests) ? j.requests : [] };
|
|
1933
|
+
} catch { return { requests: [] }; }
|
|
1934
|
+
}
|
|
1935
|
+
function _writeUserRequests(root, requests) {
|
|
1936
|
+
try {
|
|
1937
|
+
mkdirp(path.join(root, '.harness'));
|
|
1938
|
+
writeUtf8(_userRequestsPath(root), JSON.stringify({ requests, updatedAt: new Date().toISOString() }, null, 2));
|
|
1939
|
+
return true;
|
|
1940
|
+
} catch { return false; }
|
|
1941
|
+
}
|
|
1942
|
+
function _recordUserRequest(root, text, opts = {}) {
|
|
1943
|
+
if (!text || typeof text !== 'string') return null;
|
|
1944
|
+
const state = _loadUserRequests(root);
|
|
1945
|
+
// μ€λ³΅ λ°©μ§: λμΌ ν
μ€νΈ + open μν μ΄λ―Έ μ‘΄μ¬ μ skip
|
|
1946
|
+
const norm = text.trim().slice(0, 500);
|
|
1947
|
+
const dup = state.requests.find(r => r.text === norm && (r.status === 'open' || r.status === 'in-progress'));
|
|
1948
|
+
if (dup) return dup;
|
|
1949
|
+
const id = 'UR-' + String(state.requests.length + 1).padStart(4, '0');
|
|
1950
|
+
const entry = {
|
|
1951
|
+
id, text: norm, recordedAt: new Date().toISOString(),
|
|
1952
|
+
status: opts.status || 'open',
|
|
1953
|
+
linkedTaskIds: opts.linkedTaskIds || [],
|
|
1954
|
+
linkedPlanIds: opts.linkedPlanIds || [],
|
|
1955
|
+
linkedDecisionIds: opts.linkedDecisionIds || [],
|
|
1956
|
+
notes: opts.notes || ''
|
|
1957
|
+
};
|
|
1958
|
+
state.requests.push(entry);
|
|
1959
|
+
// μ΅κ·Ό 200κ°λ§ μ μ§
|
|
1960
|
+
if (state.requests.length > 200) state.requests = state.requests.slice(-200);
|
|
1961
|
+
_writeUserRequests(root, state.requests);
|
|
1962
|
+
return entry;
|
|
1963
|
+
}
|
|
1964
|
+
function _updateUserRequest(root, id, patch) {
|
|
1965
|
+
const state = _loadUserRequests(root);
|
|
1966
|
+
const idx = state.requests.findIndex(r => r.id === id);
|
|
1967
|
+
if (idx < 0) return null;
|
|
1968
|
+
state.requests[idx] = { ...state.requests[idx], ...patch, updatedAt: new Date().toISOString() };
|
|
1969
|
+
if (patch.status === 'completed' && !state.requests[idx].completedAt) state.requests[idx].completedAt = new Date().toISOString();
|
|
1970
|
+
if (patch.status === 'dropped' && !state.requests[idx].droppedAt) state.requests[idx].droppedAt = new Date().toISOString();
|
|
1971
|
+
_writeUserRequests(root, state.requests);
|
|
1972
|
+
return state.requests[idx];
|
|
1973
|
+
}
|
|
1974
|
+
// audit: open/in-progress μμ² μ€ task-log μ λ§€μΉλλ μμ
μ΄ μλ νλͺ©μ "λλ½ ν보"λ‘ λ³΄κ³
|
|
1975
|
+
function _auditUserRequests(root) {
|
|
1976
|
+
const state = _loadUserRequests(root);
|
|
1977
|
+
const open = state.requests.filter(r => r.status === 'open' || r.status === 'in-progress');
|
|
1978
|
+
const taskLog = (() => { try { return read(path.join(root, '.harness', 'task-log.md')); } catch { return ''; } })();
|
|
1979
|
+
const plan = (() => { try { return read(path.join(root, '.harness', 'plan.md')); } catch { return ''; } })();
|
|
1980
|
+
const decisions = (() => { try { return read(path.join(root, '.harness', 'decisions.md')); } catch { return ''; } })();
|
|
1981
|
+
const haystack = (taskLog + '\n' + plan + '\n' + decisions).toLowerCase();
|
|
1982
|
+
const missing = [];
|
|
1983
|
+
const tracked = [];
|
|
1984
|
+
open.forEach(req => {
|
|
1985
|
+
const linked = (req.linkedTaskIds && req.linkedTaskIds.length > 0)
|
|
1986
|
+
|| (req.linkedPlanIds && req.linkedPlanIds.length > 0)
|
|
1987
|
+
|| (req.linkedDecisionIds && req.linkedDecisionIds.length > 0);
|
|
1988
|
+
// ν€μλ λ§€μΉ β μμ² ν
μ€νΈμ μ²μ 8λ¨μ΄ μ€ 3λ¨μ΄ μ΄μ task-log/plan/decisions μ μ‘΄μ¬ β tracked
|
|
1989
|
+
const words = req.text.toLowerCase().split(/[\s,.()/\\-]+/).filter(w => w.length >= 2).slice(0, 12);
|
|
1990
|
+
const hits = words.filter(w => haystack.includes(w)).length;
|
|
1991
|
+
const matched = hits >= Math.min(3, Math.ceil(words.length * 0.5));
|
|
1992
|
+
if (linked || matched) tracked.push({ ...req, hits, words: words.length });
|
|
1993
|
+
else missing.push({ ...req, hits, words: words.length });
|
|
1994
|
+
});
|
|
1995
|
+
// 7μΌ μ΄μ 묡μ open μμ² (stale)
|
|
1996
|
+
const now = Date.now();
|
|
1997
|
+
const stale = open.filter(r => (now - new Date(r.recordedAt).getTime()) > 7 * 24 * 60 * 60 * 1000);
|
|
1998
|
+
return {
|
|
1999
|
+
total: state.requests.length,
|
|
2000
|
+
open: open.length,
|
|
2001
|
+
missing,
|
|
2002
|
+
tracked,
|
|
2003
|
+
stale,
|
|
2004
|
+
completed: state.requests.filter(r => r.status === 'completed').length,
|
|
2005
|
+
dropped: state.requests.filter(r => r.status === 'dropped').length
|
|
2006
|
+
};
|
|
2007
|
+
}
|
|
2008
|
+
|
|
1836
2009
|
// 1.9.203: μλ λΌμ΄λ plan μ 리 β μ¬μ©μ λͺ
μ
|
|
1837
2010
|
// "λ°±κ·ΈλΌμ΄λμ λ€μ μμ
μ΄ μμκ°λ₯ν μμ μκ° + μΌμ΄λ¬μλ ν΄μΌνλ μΌμ μ 리"
|
|
1838
2011
|
// λΌμ΄λ λ§λ¬΄λ¦¬ μ .harness/auto-resume-plan.json μλ μ μ₯ β λ€μ wakeup μ μ¦μ μ€ν κ°λ₯
|
|
@@ -1942,6 +2115,122 @@ function resumeCmd(root) {
|
|
|
1942
2115
|
log(grn(`β resume μ€λΉ μλ£ β κΆμ₯: leerness handoff . λλ leerness next-action take`));
|
|
1943
2116
|
}
|
|
1944
2117
|
|
|
2118
|
+
// 1.9.207: leerness requests <sub> β μ¬μ©μ μμ² λλ½ νμΈ μ μ°¨ CLI (μ¬μ©μ λͺ
μ)
|
|
2119
|
+
// audit β open μμ² μ€ task-log/plan/decisions μ λ§€μΉ μ λλ νλͺ© λ³΄κ³ (λλ½ ν보)
|
|
2120
|
+
// add β μ¬μ©μ μμ² μλ κΈ°λ‘ (μ: leerness requests add "API rate limit 5/s μ μ©")
|
|
2121
|
+
// list β λͺ¨λ μμ² μΆλ ₯ (--json μ΅μ
)
|
|
2122
|
+
// complete <id> β μμ² μλ£ νμ
|
|
2123
|
+
// drop <id> β μμ² λλ‘ νμ (μ¬μ©μ λͺ
μ μ·¨μ)
|
|
2124
|
+
function requestsCmd(root, sub, ...rest) {
|
|
2125
|
+
root = absRoot(root);
|
|
2126
|
+
const isTty = process.stdout && process.stdout.isTTY;
|
|
2127
|
+
const cyan = s => isTty ? `\x1b[36m${s}\x1b[0m` : s;
|
|
2128
|
+
const grn = s => isTty ? `\x1b[32m${s}\x1b[0m` : s;
|
|
2129
|
+
const yel = s => isTty ? `\x1b[33m${s}\x1b[0m` : s;
|
|
2130
|
+
const red = s => isTty ? `\x1b[31m${s}\x1b[0m` : s;
|
|
2131
|
+
const dim = s => isTty ? `\x1b[2m${s}\x1b[0m` : s;
|
|
2132
|
+
|
|
2133
|
+
if (!sub || sub === 'help' || sub === '--help') {
|
|
2134
|
+
log(`# leerness requests (1.9.207) β μ¬μ©μ μμ² λλ½ νμΈ μ μ°¨`);
|
|
2135
|
+
log('');
|
|
2136
|
+
log(` audit β λλ½ ν보 + tracked + stale λ³΄κ³ (--json κ°λ₯)`);
|
|
2137
|
+
log(` add "<text>" β μ¬μ©μ μμ² μλ κΈ°λ‘`);
|
|
2138
|
+
log(` list β μ 체 μμ² μΆλ ₯ (--json κ°λ₯, --status open|completed|dropped)`);
|
|
2139
|
+
log(` complete <id> β μμ² μλ£ νμ (μ: UR-0003)`);
|
|
2140
|
+
log(` drop <id> β μμ² λλ‘ νμ`);
|
|
2141
|
+
return;
|
|
2142
|
+
}
|
|
2143
|
+
|
|
2144
|
+
if (sub === 'add') {
|
|
2145
|
+
const text = rest.filter(x => !x.startsWith('-')).join(' ');
|
|
2146
|
+
if (!text) { console.error('Usage: leerness requests add "<request text>"'); process.exit(1); }
|
|
2147
|
+
const entry = _recordUserRequest(root, text);
|
|
2148
|
+
if (!entry) { console.error('failed to record'); process.exit(1); }
|
|
2149
|
+
if (has('--json')) { log(JSON.stringify(entry, null, 2)); return; }
|
|
2150
|
+
log(grn(`β recorded ${entry.id}: ${entry.text}`));
|
|
2151
|
+
return;
|
|
2152
|
+
}
|
|
2153
|
+
|
|
2154
|
+
if (sub === 'list') {
|
|
2155
|
+
const state = _loadUserRequests(root);
|
|
2156
|
+
const filterStatus = arg('--status', null);
|
|
2157
|
+
let list = state.requests;
|
|
2158
|
+
if (filterStatus) list = list.filter(r => r.status === filterStatus);
|
|
2159
|
+
if (has('--json')) { log(JSON.stringify({ total: state.requests.length, filtered: list.length, requests: list }, null, 2)); return; }
|
|
2160
|
+
log(cyan(`# leerness requests list (1.9.207)`));
|
|
2161
|
+
log(` total ${state.requests.length}${filterStatus ? ` Β· filter status=${filterStatus} β ${list.length}` : ''}`);
|
|
2162
|
+
log('');
|
|
2163
|
+
if (list.length === 0) { log(dim(' (μμ)')); return; }
|
|
2164
|
+
for (const r of list) {
|
|
2165
|
+
const statusIcon = r.status === 'completed' ? 'β' : (r.status === 'dropped' ? 'β' : (r.status === 'in-progress' ? 'βΆ' : 'β―'));
|
|
2166
|
+
const recordedDay = (r.recordedAt || '').slice(0, 10);
|
|
2167
|
+
log(` ${statusIcon} [${r.id}] ${dim(recordedDay)} ${r.text.slice(0, 100)}${r.text.length > 100 ? 'β¦' : ''}`);
|
|
2168
|
+
if (r.linkedTaskIds && r.linkedTaskIds.length > 0) log(dim(` linked tasks: ${r.linkedTaskIds.join(', ')}`));
|
|
2169
|
+
}
|
|
2170
|
+
return;
|
|
2171
|
+
}
|
|
2172
|
+
|
|
2173
|
+
if (sub === 'complete') {
|
|
2174
|
+
const id = rest[0];
|
|
2175
|
+
if (!id) { console.error('Usage: leerness requests complete <id>'); process.exit(1); }
|
|
2176
|
+
const updated = _updateUserRequest(root, id, { status: 'completed' });
|
|
2177
|
+
if (!updated) { console.error(`request not found: ${id}`); process.exit(1); }
|
|
2178
|
+
if (has('--json')) { log(JSON.stringify(updated, null, 2)); return; }
|
|
2179
|
+
log(grn(`β completed ${updated.id}`));
|
|
2180
|
+
return;
|
|
2181
|
+
}
|
|
2182
|
+
|
|
2183
|
+
if (sub === 'drop') {
|
|
2184
|
+
const id = rest[0];
|
|
2185
|
+
if (!id) { console.error('Usage: leerness requests drop <id>'); process.exit(1); }
|
|
2186
|
+
const updated = _updateUserRequest(root, id, { status: 'dropped' });
|
|
2187
|
+
if (!updated) { console.error(`request not found: ${id}`); process.exit(1); }
|
|
2188
|
+
if (has('--json')) { log(JSON.stringify(updated, null, 2)); return; }
|
|
2189
|
+
log(yel(`β dropped ${updated.id}`));
|
|
2190
|
+
return;
|
|
2191
|
+
}
|
|
2192
|
+
|
|
2193
|
+
if (sub === 'audit') {
|
|
2194
|
+
const audit = _auditUserRequests(root);
|
|
2195
|
+
if (has('--json')) { log(JSON.stringify(audit, null, 2)); return; }
|
|
2196
|
+
log(cyan(`# leerness requests audit (1.9.207) β μ¬μ©μ μμ² λλ½ νμΈ μ μ°¨`));
|
|
2197
|
+
log('');
|
|
2198
|
+
log(` π ν΅κ³: total ${audit.total} Β· open ${audit.open} Β· completed ${audit.completed} Β· dropped ${audit.dropped}`);
|
|
2199
|
+
log('');
|
|
2200
|
+
if (audit.missing.length === 0) {
|
|
2201
|
+
log(grn(` β λλ½ μμ β open μμ² λͺ¨λ task-log/plan/decisions μ νμ μμ`));
|
|
2202
|
+
} else {
|
|
2203
|
+
log(red(` β λλ½ ν보 ${audit.missing.length}건 (open μνμ΄λ task/plan/decisions λ§€μΉ μμ):`));
|
|
2204
|
+
for (const m of audit.missing) {
|
|
2205
|
+
log(` β’ [${m.id}] ${m.text.slice(0, 90)}${m.text.length > 90 ? 'β¦' : ''}`);
|
|
2206
|
+
log(dim(` ${m.recordedAt.slice(0, 10)} Β· hits=${m.hits}/${m.words}`));
|
|
2207
|
+
}
|
|
2208
|
+
log('');
|
|
2209
|
+
log(dim(` β κΆμ₯: λλ½ νλͺ©λ³ leerness task add "<μμ²>" λλ leerness requests complete <id>`));
|
|
2210
|
+
}
|
|
2211
|
+
if (audit.tracked.length > 0) {
|
|
2212
|
+
log('');
|
|
2213
|
+
log(grn(` β tracked ${audit.tracked.length}건 (open + task/plan/decisions λ§€μΉλ¨):`));
|
|
2214
|
+
for (const t of audit.tracked.slice(0, 5)) {
|
|
2215
|
+
log(` β’ [${t.id}] ${t.text.slice(0, 80)}${t.text.length > 80 ? 'β¦' : ''} ${dim(`(hits=${t.hits})`)}`);
|
|
2216
|
+
}
|
|
2217
|
+
}
|
|
2218
|
+
if (audit.stale.length > 0) {
|
|
2219
|
+
log('');
|
|
2220
|
+
log(yel(` β³ stale ${audit.stale.length}건 (7μΌ+ open):`));
|
|
2221
|
+
for (const s of audit.stale.slice(0, 5)) {
|
|
2222
|
+
const days = Math.floor((Date.now() - new Date(s.recordedAt).getTime()) / 86400000);
|
|
2223
|
+
log(` β’ [${s.id}] ${days}μΌ ${s.text.slice(0, 70)}β¦`);
|
|
2224
|
+
}
|
|
2225
|
+
}
|
|
2226
|
+
return;
|
|
2227
|
+
}
|
|
2228
|
+
|
|
2229
|
+
console.error(`Unknown subcommand: ${sub}`);
|
|
2230
|
+
console.error(`Run: leerness requests help`);
|
|
2231
|
+
process.exit(1);
|
|
2232
|
+
}
|
|
2233
|
+
|
|
1945
2234
|
// 1.9.199: wakeup miss μλ ν볡 κ°ν β last-handoff timestamp κΈ°λ‘ + 25min κΈ°λ interval μ λ° μΈ‘μ
|
|
1946
2235
|
// μ¬μ©μ λͺ
μ (1.9.198 νμ): "22:01μ λΌμ΄λμ μλμ§μ
λμ§μμμ΄"
|
|
1947
2236
|
// 1.9.196 task-log mtime κΈ°λ° detector λ task-log κ° μμ£Ό μ μ
λ°μ΄νΈλλ©΄ false positive.
|
|
@@ -3976,10 +4265,19 @@ function handoff(root) {
|
|
|
3976
4265
|
parts.push(`π backend ${pb.ready}/${pb.total} (${ageLabel}${pb.expired ? 'β ' : 'β'})`);
|
|
3977
4266
|
}
|
|
3978
4267
|
} catch {}
|
|
4268
|
+
// 13) 1.9.207: μ¬μ©μ μμ² λλ½ νμΈ μ μ°¨ (μ¬μ©μ λͺ
μ) β λλ½ ν보 β₯ 1 μ ν€λλΌμΈ λ
ΈμΆ
|
|
4269
|
+
try {
|
|
4270
|
+
const audit = _auditUserRequests(root);
|
|
4271
|
+
if (audit.missing && audit.missing.length > 0) {
|
|
4272
|
+
parts.push(`π₯ λ―Έλ΅ μμ² ${audit.missing.length}건`);
|
|
4273
|
+
} else if (audit.open > 0) {
|
|
4274
|
+
parts.push(`π₯ μμ² ${audit.open} (tracked)`);
|
|
4275
|
+
}
|
|
4276
|
+
} catch {}
|
|
3979
4277
|
if (parts.length) {
|
|
3980
4278
|
const isTty = process.stdout && process.stdout.isTTY;
|
|
3981
4279
|
const cy = s => isTty ? `\x1b[36m${s}\x1b[0m` : s;
|
|
3982
|
-
log(cy(`π ν€λλΌμΈ (1.9.81/93/113/152/162/192/197/204): ${parts.join(' Β· ')}`));
|
|
4280
|
+
log(cy(`π ν€λλΌμΈ (1.9.81/93/113/152/162/192/197/204/207): ${parts.join(' Β· ')}`));
|
|
3983
4281
|
}
|
|
3984
4282
|
} catch {}
|
|
3985
4283
|
}
|
|
@@ -15268,6 +15566,8 @@ async function main() {
|
|
|
15268
15566
|
if (cmd === 'next-action') return nextActionCmd(arg('--path', process.cwd()), args[1], ...args.slice(2));
|
|
15269
15567
|
// 1.9.203: leerness resume β auto-resume-plan μ½κ³ λ€μ λΌμ΄λ μ¦μ μλ΄ (μ¬μ©μ λͺ
μ)
|
|
15270
15568
|
if (cmd === 'resume') return resumeCmd(arg('--path', process.cwd()));
|
|
15569
|
+
// 1.9.207: leerness requests <audit|add|list|complete|drop> β μ¬μ©μ μμ² λλ½ νμΈ μ μ°¨ (μ¬μ©μ λͺ
μ)
|
|
15570
|
+
if (cmd === 'requests') return requestsCmd(arg('--path', process.cwd()), args[1], ...args.slice(2));
|
|
15271
15571
|
if (cmd === 'rule' && args[1] === 'add') return ruleAdd(arg('--path', process.cwd()), args.slice(2).filter(x => !x.startsWith('-')).join(' '));
|
|
15272
15572
|
if (cmd === 'rule' && args[1] === 'list') return ruleList(arg('--path', process.cwd()));
|
|
15273
15573
|
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.
|
|
3
|
+
"version": "1.9.207",
|
|
4
4
|
"description": "Leerness: λΉνκ΄΄ λ§μ΄κ·Έλ μ΄μ
, μλ λ²μ κ°μ§Β·μ
λ°μ΄νΈ, κ³ν/μ§ν/νΈλμ€ν μλν, κ²μΌλ¦Β·μν¬λ¦ΏΒ·μΈμ½λ© μλ κ°λ, Claude Code μ¬λμ ν΅ν©μ κ°μΆ νκ΅μ΄ μ°μ AI κ°λ° νλ€μ€.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"leerness",
|