leerness 1.9.193 β 1.9.194
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 +53 -0
- package/README.md +3 -3
- package/bin/harness.js +152 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,58 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.9.194 β 2026-05-21
|
|
4
|
+
|
|
5
|
+
**π― EμΆ (κ²μΌλ¦ λ°©μ§) λ³΄κ° β handoff λ€μ λ¨κ³ μλ μ μ + 24h+ 무μ§μ² lazy κ°μ§.**
|
|
6
|
+
|
|
7
|
+
μμ¨ λͺ¨λ 124 λΌμ΄λ. 1.9.192 CμΆ / 1.9.193 BμΆ λ³΄κ°μ μ΄μ΄ **EμΆ (9/10 β λͺ©ν 9.5/10)** 보κ°.
|
|
8
|
+
|
|
9
|
+
### μ¬μ©μ μλ μ λ ¬ (1.9.191 verbatim)
|
|
10
|
+
> *"κ²μΌλ¦ λ°©μ§λ±λ± μ΅κ³ μ λꡬ"*
|
|
11
|
+
|
|
12
|
+
### 1. handoff λ€μ λ¨κ³ μλ μ μ (EμΆ ν΅μ¬)
|
|
13
|
+
- νμ¬ in-progress task description + Memory Surface (decisions/lessons/plan) μ‘°ν© β λ€μ λ¨κ³ 1-3κ° μ μ
|
|
14
|
+
- μ¬μ©μ/AI κ° "Next Exact Step" μ μ§μ μ±μ°μ§ μμλ μ¦μ λ
ΈμΆ
|
|
15
|
+
- **7κ° ν΄λ¦¬μ€ν±**:
|
|
16
|
+
1. lessons.md μ€ν¨ λ§€μΉ β ννΌ μ λ΅ μ μ© (`leerness lessons --auto`)
|
|
17
|
+
2. plan.md milestone λ§€μΉ β milestone κ²μ¦ (`leerness plan list`)
|
|
18
|
+
3. decisions.md κ²°μ λ§€μΉ β μν₯ νμΈ (`leerness decision list`)
|
|
19
|
+
4. review-evidence.md λΆμ¬ β e2e μ€ν (`node ./scripts/e2e.js`)
|
|
20
|
+
5. 24h+ μ 체 β task status κ°±μ (`leerness task update`)
|
|
21
|
+
6. λ²μ λ³λ task β CHANGELOG/README κ°±μ νμΈ (`leerness whats-new`)
|
|
22
|
+
7. stress test λλ½ β μ stress μμ± κΆμ₯
|
|
23
|
+
- λκΈ°: `--no-next-actions` λλ `LEERNESS_NO_NEXT_ACTIONS=1`
|
|
24
|
+
|
|
25
|
+
### 2. 24h+ 무 μ§μ² lazy κ°μ§
|
|
26
|
+
- progress-tracker.md mtime β₯ 24h β `## β μ§μ² μ 체 κ°μ§` μλ μΆλ ₯
|
|
27
|
+
- νμ¬ in-progress task ID + request μμ½ νμ
|
|
28
|
+
- κΆμ₯ λͺ
λ Ή: `leerness task update <id> --status` / `leerness lazy detect --json`
|
|
29
|
+
- λκΈ°: `--no-lazy-warn` λλ `LEERNESS_NO_LAZY_WARN=1`
|
|
30
|
+
|
|
31
|
+
### 3. λμ νκ· (1.9.188~193) β λͺ¨λ μ μ§
|
|
32
|
+
- [1.9.193] agents multi consensus β lessons.md μλ
|
|
33
|
+
- [1.9.192] _loadOfficialSkillCache + 24h μΊμ
|
|
34
|
+
- [1.9.191] ꡬ쑰 μ΅μ ν λ³΄κ³ μ 88/100
|
|
35
|
+
- [1.9.190] _selectOne/_selectMany Ctrl+C μ¦μ μ’
λ£
|
|
36
|
+
- [1.9.189] _showSlashCommandList + Tab cycle ν μ€ κ°±μ
|
|
37
|
+
- [1.9.188] stdin prompt μ λ¬
|
|
38
|
+
|
|
39
|
+
### 4. stress-v139 β 15/15 PASS
|
|
40
|
+
- EμΆ λ³΄κ° (6: ν¨μ + μΉμ
+ μμ μν¬μ€νμ΄μ€ ν΅ν©) + μ±λ₯ (2) + λμ νκ· (7)
|
|
41
|
+
- μμ μν¬μ€νμ΄μ€ mtime 25h κ°μ β β μ§μ² μ 체 κ°μ§ β
|
|
42
|
+
- μ±λ₯: --version cold start avg **479 ms** Β· MCP 54 λꡬ **416 ms**
|
|
43
|
+
|
|
44
|
+
### 5. 5μΆ λ§€νΈλ¦μ€ λ³λ
|
|
45
|
+
| μΆ | 1.9.193 | 1.9.194 | Ξ |
|
|
46
|
+
|---|---|---|---|
|
|
47
|
+
| E. κ²μΌλ¦ λ°©μ§ | 9/10 | **9.5/10** | +0.5 (λ€μ λ¨κ³ μλ μ μ + lazy κ°μ§) |
|
|
48
|
+
| μ’
ν© | 45.5/50 (91%) | **46/50 (92%)** | +1% |
|
|
49
|
+
|
|
50
|
+
### 6. μλ release νλ¦
|
|
51
|
+
- main μλ push **56 λΌμ΄λ μ°μ** (1.9.140~194)
|
|
52
|
+
- npm publish μλ (1.9.178~)
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
3
56
|
## 1.9.193 β 2026-05-21
|
|
4
57
|
|
|
5
58
|
**π€ BμΆ (λ©ν° Sub-Agent μ€μΌμ€νΈλΌ) λ³΄κ° β agents multi consensus κ²°κ³Ό μλ lessons.md μ μ₯ + μΊμ 7μΌ stale hint.**
|
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.194 AI Agent Reliability Harness + Sandbox β
|
|
16
16
|
β verify Β· remember Β· orchestrate Β· audit Β· sandbox Β· drift β
|
|
17
|
-
β
|
|
17
|
+
β π― handoff next-actions μλ μ μ Β· 92/100 Β· 124 λΌμ΄λ β
|
|
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.
|
|
10
|
+
const VERSION = '1.9.194';
|
|
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 μ²λ¦¬).
|
|
@@ -1662,6 +1662,112 @@ async function skillAutoCacheCmd(root, sub) {
|
|
|
1662
1662
|
if (c.expired) log(` β κ°±μ : leerness skill auto-cache refresh`);
|
|
1663
1663
|
}
|
|
1664
1664
|
|
|
1665
|
+
// 1.9.194: EμΆ (κ²μΌλ¦ λ°©μ§) β handoff μμ λ€μ λ¨κ³ 1-3κ° μλ μ μ
|
|
1666
|
+
// νμ¬ in-progress task description + Memory Surface (decisions/lessons/plan) μ‘°ν© β
|
|
1667
|
+
// "λ€μ λ¨κ³λ‘ 무μμ ν μ§" μΆλ‘ (μ¬μ©μ/AI μ§μ μ
λ ₯ μμ΄ μ¦μ λ
ΈμΆ)
|
|
1668
|
+
// μκ³ λ¦¬μ¦:
|
|
1669
|
+
// 1) lessons.md μ keyword λ§€μΉ + μ€ν¨/λ‘€λ°± ν€μλ β "ννΌ μ λ΅ μ μ©"
|
|
1670
|
+
// 2) plan.md μ keyword λ§€μΉ + M-XXXX β "κ³ν milestone κ²μ¦"
|
|
1671
|
+
// 3) decisions.md μ keyword λ§€μΉ β "κ²°μ N μν₯ νμΈ"
|
|
1672
|
+
// 4) review-evidence.md λΆμ¬ β "verify-code λλ e2e μ€ν"
|
|
1673
|
+
// 5) progress-tracker.md 24h+ μ 체 β "task status κ°±μ "
|
|
1674
|
+
// 6) CHANGELOG λ³΄κ° λΆμ¬ β "λ²μ λ³κ²½ μ CHANGELOG κ°±μ "
|
|
1675
|
+
// 7) stress-vXXX λλ½ β "stress test μμ±"
|
|
1676
|
+
// 1.9.116 brainstorm νμμ λ€λ₯Έ μ : brainstorm μ "κ΄λ ¨ hits νμ" / next-actions λ "λ€μ μ€ν λͺ
λ Ή μ μ"
|
|
1677
|
+
function _suggestNextActions(root, latestRow, keyword) {
|
|
1678
|
+
const actions = [];
|
|
1679
|
+
const taskText = String(latestRow.request || '').toLowerCase();
|
|
1680
|
+
const fuzzyRe = keyword ? new RegExp(escapeRegex(keyword.slice(0, Math.max(4, Math.floor(keyword.length * 0.7)))), 'i') : null;
|
|
1681
|
+
|
|
1682
|
+
// 1) lessons.md μ€ν¨ λ§€μΉ β ννΌ μ λ΅
|
|
1683
|
+
try {
|
|
1684
|
+
if (fuzzyRe && exists(lessonsPath(root))) {
|
|
1685
|
+
const lt = read(lessonsPath(root));
|
|
1686
|
+
const blocks = lt.split(/\n### /);
|
|
1687
|
+
const hits = blocks.filter(b => fuzzyRe.test(b) && /(μ€ν¨|fail|λ‘€λ°±|λ²κ·Έ|incomplete)/i.test(b));
|
|
1688
|
+
if (hits.length > 0) {
|
|
1689
|
+
actions.push({ icon: 'π‘', title: `κ³Όκ±° μ€ν¨ ννΌ β lessons.md μ "${keyword}" κ΄λ ¨ ${hits.length}건`, command: `leerness lessons --auto --path .` });
|
|
1690
|
+
}
|
|
1691
|
+
}
|
|
1692
|
+
} catch {}
|
|
1693
|
+
|
|
1694
|
+
// 2) plan.md milestone λ§€μΉ β milestone κ²μ¦
|
|
1695
|
+
try {
|
|
1696
|
+
if (fuzzyRe && exists(planPath(root))) {
|
|
1697
|
+
const pt = read(planPath(root));
|
|
1698
|
+
const milestones = (pt.match(/^### (M-\d{4})\..*$/gm) || []).filter(l => fuzzyRe.test(l));
|
|
1699
|
+
if (milestones.length > 0) {
|
|
1700
|
+
const m = milestones[0].match(/M-\d{4}/);
|
|
1701
|
+
if (m) actions.push({ icon: 'π―', title: `plan.md milestone ${m[0]} κ²μ¦ β "${keyword}" κ΄λ ¨`, command: `leerness plan list --filter "${keyword}"` });
|
|
1702
|
+
}
|
|
1703
|
+
}
|
|
1704
|
+
} catch {}
|
|
1705
|
+
|
|
1706
|
+
// 3) decisions.md κ²°μ λ§€μΉ
|
|
1707
|
+
try {
|
|
1708
|
+
if (fuzzyRe && exists(decisionsPath(root))) {
|
|
1709
|
+
const dt = read(decisionsPath(root));
|
|
1710
|
+
const blocks = _extractDecisionBlocks(dt);
|
|
1711
|
+
const hits = blocks.filter(b => fuzzyRe.test(b));
|
|
1712
|
+
if (hits.length > 0) {
|
|
1713
|
+
actions.push({ icon: 'π', title: `decisions.md "${keyword}" κ΄λ ¨ κ²°μ ${hits.length}건 μν₯ νμΈ`, command: `leerness decision list --filter "${keyword}"` });
|
|
1714
|
+
}
|
|
1715
|
+
}
|
|
1716
|
+
} catch {}
|
|
1717
|
+
|
|
1718
|
+
// 4) review-evidence.md λΆμ¬ β e2e
|
|
1719
|
+
try {
|
|
1720
|
+
if (!exists(evidencePath(root)) || fs.statSync(evidencePath(root)).size < 100) {
|
|
1721
|
+
actions.push({ icon: 'π§ͺ', title: `review-evidence.md λΉμ΄μμ β e2e λλ verify-code μ€ν`, command: `node ./scripts/e2e.js` });
|
|
1722
|
+
}
|
|
1723
|
+
} catch {}
|
|
1724
|
+
|
|
1725
|
+
// 5) 24h+ μ 체 β task status κ°±μ (handoff lazy-warn κ³Ό λ³κ° β λ€μ λ¨κ³ λͺ
λ Ή)
|
|
1726
|
+
try {
|
|
1727
|
+
const pp = progressPath(root);
|
|
1728
|
+
if (exists(pp)) {
|
|
1729
|
+
const ageHours = Math.floor((Date.now() - fs.statSync(pp).mtimeMs) / 3600000);
|
|
1730
|
+
if (ageHours >= 24 && latestRow.id) {
|
|
1731
|
+
actions.push({ icon: 'π', title: `progress-tracker ${ageHours}h μ 체 β task ${latestRow.id} status κ°±μ `, command: `leerness task update ${latestRow.id} --status completed` });
|
|
1732
|
+
}
|
|
1733
|
+
}
|
|
1734
|
+
} catch {}
|
|
1735
|
+
|
|
1736
|
+
// 6) CHANGELOG / README λ²μ μΌμΉ νμΈ (1.9.X bump ν μμ£Ό λλ½λλ λ¨κ³)
|
|
1737
|
+
try {
|
|
1738
|
+
if (/(\d\.\d\.\d+)/.test(taskText) || /(bump|version|release)/i.test(taskText)) {
|
|
1739
|
+
actions.push({ icon: 'π', title: `λ²μ λ³λ task β CHANGELOG.md / README.md κ°±μ νμΈ`, command: `node ./bin/harness.js whats-new .` });
|
|
1740
|
+
}
|
|
1741
|
+
} catch {}
|
|
1742
|
+
|
|
1743
|
+
// 7) stress test λλ½ (μμ¨ λΌμ΄λ μμ£Ό λλ½)
|
|
1744
|
+
try {
|
|
1745
|
+
const stressDir = path.resolve(root, '..', '_apps', 'leerness-stress', 'bin');
|
|
1746
|
+
if (exists(stressDir)) {
|
|
1747
|
+
const files = fs.readdirSync(stressDir).filter(f => /^stress-v\d+\.js$/.test(f));
|
|
1748
|
+
if (files.length > 0) {
|
|
1749
|
+
const versions = files.map(f => Number(f.match(/v(\d+)/)[1])).sort((a, b) => b - a);
|
|
1750
|
+
const latest = versions[0];
|
|
1751
|
+
// νμ¬ λΌμ΄λ = 1.9.X μμ stress-v(X-55) μ λ? λ¨μν μ΅μ stress κ° 7μΌ+ μ€λλλ©΄ κΆμ₯
|
|
1752
|
+
const latestFile = path.join(stressDir, `stress-v${latest}.js`);
|
|
1753
|
+
const ageHours = Math.floor((Date.now() - fs.statSync(latestFile).mtimeMs) / 3600000);
|
|
1754
|
+
if (ageHours >= 24 && /(bump|version|보κ°|μΆκ°|κΈ°λ₯)/.test(taskText)) {
|
|
1755
|
+
actions.push({ icon: 'π§¬', title: `stress-v${latest} λ§μ§λ§ κ°±μ ${ageHours}h μ β μ stress test μμ± κΆμ₯`, command: `node _apps/leerness-stress/bin/stress-v${latest+1}.js` });
|
|
1756
|
+
}
|
|
1757
|
+
}
|
|
1758
|
+
}
|
|
1759
|
+
} catch {}
|
|
1760
|
+
|
|
1761
|
+
// μ€λ³΅ μ κ±° (icon+title κΈ°μ€) + top 3
|
|
1762
|
+
const seen = new Set();
|
|
1763
|
+
return actions.filter(a => {
|
|
1764
|
+
const key = a.icon + a.title.slice(0, 30);
|
|
1765
|
+
if (seen.has(key)) return false;
|
|
1766
|
+
seen.add(key);
|
|
1767
|
+
return true;
|
|
1768
|
+
}).slice(0, 3);
|
|
1769
|
+
}
|
|
1770
|
+
|
|
1665
1771
|
// 1.9.182: handoff 컨ν
μ€νΈ (νμ¬ in-progress task) μμ μλ query μΆμΆ
|
|
1666
1772
|
function _autoInstallQueryFromHandoff(root) {
|
|
1667
1773
|
try {
|
|
@@ -3557,6 +3663,51 @@ function handoff(root) {
|
|
|
3557
3663
|
}
|
|
3558
3664
|
} catch {}
|
|
3559
3665
|
}
|
|
3666
|
+
// 1.9.194: EμΆ (κ²μΌλ¦ λ°©μ§) λ³΄κ° β handoff λ€μ λ¨κ³ 1-3κ° μλ μ μ
|
|
3667
|
+
// νμ¬ in-progress task description + Memory Surface (decisions/lessons/plan) μ‘°ν© β
|
|
3668
|
+
// "λ€μ λ¨κ³λ‘ 무μμ ν μ§" 3κ°λ₯Ό μ¦μ μ μ (μ¬μ©μκ° μ§μ μ±μ°μ§ μμλ AIμκ² λ
ΈμΆλ¨)
|
|
3669
|
+
// skill installed μ¬λΆμ λ¬΄κ΄ β keyword λ§ μμΌλ©΄ λμ (κ²μΌλ¦ λ°©μ§λ λͺ¨λ μν¬μ€νμ΄μ€ νμ)
|
|
3670
|
+
// λκΈ°: --no-next-actions λλ LEERNESS_NO_NEXT_ACTIONS=1
|
|
3671
|
+
if (!has('--no-next-actions') && !has('--quiet') && process.env.LEERNESS_NO_NEXT_ACTIONS !== '1') {
|
|
3672
|
+
try {
|
|
3673
|
+
const actions = _suggestNextActions(root, latestRow, keyword);
|
|
3674
|
+
if (actions.length > 0) {
|
|
3675
|
+
const isTty = process.stdout && process.stdout.isTTY;
|
|
3676
|
+
const grn = s => isTty ? `\x1b[32m${s}\x1b[0m` : s;
|
|
3677
|
+
const dim = s => isTty ? `\x1b[2m${s}\x1b[0m` : s;
|
|
3678
|
+
log(grn(`## π― λ€μ λ¨κ³ μλ μ μ (1.9.194 EμΆ β κ²μΌλ¦ λ°©μ§) β ν€μλ "${keyword}"`));
|
|
3679
|
+
for (const a of actions) {
|
|
3680
|
+
log(dim(` ${a.icon} ${a.title}`));
|
|
3681
|
+
if (a.command) log(dim(` \`${a.command}\``));
|
|
3682
|
+
}
|
|
3683
|
+
log(dim(` β μ§μ μ
λ ₯: leerness next-action add "<text>"`));
|
|
3684
|
+
log('');
|
|
3685
|
+
}
|
|
3686
|
+
} catch {}
|
|
3687
|
+
}
|
|
3688
|
+
// 1.9.194: 24h+ 무 μ§μ² lazy κ°μ§ β progress-tracker mtime κΈ°λ°
|
|
3689
|
+
// νμ¬ in-progress task κ° 24h μ΄μ λ³λ μμΌλ©΄ "lazy μμ¬" hint
|
|
3690
|
+
// λκΈ°: --no-lazy-warn λλ LEERNESS_NO_LAZY_WARN=1
|
|
3691
|
+
if (!has('--no-lazy-warn') && !has('--quiet') && process.env.LEERNESS_NO_LAZY_WARN !== '1') {
|
|
3692
|
+
try {
|
|
3693
|
+
const pp = progressPath(root);
|
|
3694
|
+
if (exists(pp)) {
|
|
3695
|
+
const ageMs = Date.now() - fs.statSync(pp).mtimeMs;
|
|
3696
|
+
const ageHours = Math.floor(ageMs / 3600000);
|
|
3697
|
+
if (ageHours >= 24) {
|
|
3698
|
+
const isTty = process.stdout && process.stdout.isTTY;
|
|
3699
|
+
const yel = s => isTty ? `\x1b[33m${s}\x1b[0m` : s;
|
|
3700
|
+
const dim = s => isTty ? `\x1b[2m${s}\x1b[0m` : s;
|
|
3701
|
+
const ageLabel = ageHours < 48 ? `${ageHours}h` : `${Math.floor(ageHours/24)}d`;
|
|
3702
|
+
log(yel(`## β μ§μ² μ 체 κ°μ§ (1.9.194 EμΆ) β progress-tracker λ§μ§λ§ λ³λ ${ageLabel} μ `));
|
|
3703
|
+
log(dim(` νμ¬ in-progress task: ${latestRow.id} ${(latestRow.request || '').slice(0, 60)}`));
|
|
3704
|
+
log(dim(` β λ³κ²½: leerness task update ${latestRow.id} --status in-progress λλ --status completed`));
|
|
3705
|
+
log(dim(` β νκ³ : leerness lazy detect --json`));
|
|
3706
|
+
log('');
|
|
3707
|
+
}
|
|
3708
|
+
}
|
|
3709
|
+
} catch {}
|
|
3710
|
+
}
|
|
3560
3711
|
}
|
|
3561
3712
|
}
|
|
3562
3713
|
} catch {}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "leerness",
|
|
3
|
-
"version": "1.9.
|
|
3
|
+
"version": "1.9.194",
|
|
4
4
|
"description": "Leerness: λΉνκ΄΄ λ§μ΄κ·Έλ μ΄μ
, μλ λ²μ κ°μ§Β·μ
λ°μ΄νΈ, κ³ν/μ§ν/νΈλμ€ν μλν, κ²μΌλ¦Β·μν¬λ¦ΏΒ·μΈμ½λ© μλ κ°λ, Claude Code μ¬λμ ν΅ν©μ κ°μΆ νκ΅μ΄ μ°μ AI κ°λ° νλ€μ€.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"leerness",
|