leerness 1.9.201 β 1.9.203
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 +111 -0
- package/README.md +3 -3
- package/bin/harness.js +224 -3
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,116 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.9.203 β 2026-05-22
|
|
4
|
+
|
|
5
|
+
**π μλ λΌμ΄λ plan μλ μ 리 + `leerness resume` μ κ· CLI (μ¬μ©μ λͺ
μ).**
|
|
6
|
+
|
|
7
|
+
### μ¬μ©μ λͺ
μ
|
|
8
|
+
> *"μλλͺ¨λλ λ°±κ·ΈλΌμ΄λμ λ€μ μμ
μ΄ μμκ°λ₯ν μμ μκ°μ μ€μ ν΄μ λ°±κ·ΈλΌμ΄λμμ μλ νΈλ¦¬κ±° κ°μκ±Έ ꡬννκ³ μΌμ΄λ¬μλ ν΄μΌνλ μΌμ μ 리ν΄μ λ μ§ννκ³ λ°λ³΅μΌλ‘ νλ건 μ΄λ¨κΉ"*
|
|
9
|
+
|
|
10
|
+
### 1. `.harness/auto-resume-plan.json` μλ μ μ₯
|
|
11
|
+
- λΌμ΄λ λ§λ¬΄λ¦¬ (release sync-main μ npm publish μλ£ ν) **μλ μ μ₯**
|
|
12
|
+
- plan ꡬ쑰:
|
|
13
|
+
- `savedAt`, `nextRoundVersion`, `expectedFireAt`, `intervalMin`
|
|
14
|
+
- `focus` (μμ ν
μ€νΈ)
|
|
15
|
+
- `contextSnapshot` (currentVersion, activeTaskId, activeTaskRequest, memorySurface, r0001Rule)
|
|
16
|
+
- `nextActions` (1.9.201 next-action-queue snapshot)
|
|
17
|
+
- ν¨μ: `_loadAutoResumePlan` / `_writeAutoResumePlan` / `_buildAutoResumePlan` / `_autoResumePlanPath`
|
|
18
|
+
|
|
19
|
+
### 2. `leerness resume` μ κ· CLI
|
|
20
|
+
μΌμ΄λ¬μ λ μ¦μ 무μλΆν° ν μ§ νλμ:
|
|
21
|
+
```
|
|
22
|
+
$ leerness resume
|
|
23
|
+
# π leerness resume (1.9.203 μλ λΌμ΄λ plan μ μ©)
|
|
24
|
+
π
plan μ μ₯: 2026-05-22T00:10:10.797Z (15λΆ μ )
|
|
25
|
+
β° μμ fire: 2026-05-22T00:35:10.797Z (μ μ)
|
|
26
|
+
π― focus: λ€μ λΌμ΄λ: handoff β next-action take β μ¬μ©μ λͺ
μ λλ 5μΆ λ§€νΈλ¦μ€ 보κ°
|
|
27
|
+
|
|
28
|
+
## λ€μ λΌμ΄λ: next after 1.9.203
|
|
29
|
+
νμ¬ λ²μ : 1.9.203
|
|
30
|
+
νμ± task: T-9999 β ...
|
|
31
|
+
memory: T2/D15/R1/L3
|
|
32
|
+
λ£°: 25λΆ κ°κ²© (μ¬μ©μ λͺ
μ, R-0001)
|
|
33
|
+
|
|
34
|
+
## μ¬μ μ 리λ next-actions (3건)
|
|
35
|
+
π‘ lessons.md "X" κ΄λ ¨ ...
|
|
36
|
+
`leerness lessons --auto --path .`
|
|
37
|
+
...
|
|
38
|
+
β μ¦μ task μΆκ°: leerness next-action take
|
|
39
|
+
|
|
40
|
+
β resume μ€λΉ μλ£ β κΆμ₯: leerness handoff . λλ leerness next-action take
|
|
41
|
+
```
|
|
42
|
+
- `--json` μ΅μ
(μλν/MCP)
|
|
43
|
+
|
|
44
|
+
### 3. handoff μλ plan μλ¦Ό
|
|
45
|
+
handoff μ§μ
μ plan μ‘΄μ¬ μ μλ λ
ΈμΆ:
|
|
46
|
+
```
|
|
47
|
+
## π auto-resume-plan λ‘λ (1.9.203) β 15λΆ μ μ μ₯ (μ μ)
|
|
48
|
+
π― focus: λ€μ λΌμ΄λ: ...
|
|
49
|
+
π¦ λ€μ λ²μ : next after 1.9.203
|
|
50
|
+
π₯ μ¬μ μ 리λ actions: 3건 β leerness next-action take
|
|
51
|
+
β μμΈ: leerness resume
|
|
52
|
+
```
|
|
53
|
+
λκΈ°: `LEERNESS_NO_RESUME_PLAN=1`
|
|
54
|
+
|
|
55
|
+
### 4. μμ¨ λͺ¨λ cycle μμ±
|
|
56
|
+
- λΌμ΄λ λ§λ¬΄λ¦¬ β plan μλ μ μ₯ β ScheduleWakeup 25λΆ β wakeup β handoff plan μλ λ‘λ β resume / next-action take β μ¦μ μ§μ
|
|
57
|
+
|
|
58
|
+
### 5. λμ νκ· (1.9.197~202) β λͺ¨λ μ μ§
|
|
59
|
+
|
|
60
|
+
### 6. stress-v148 β 17/17 PASS
|
|
61
|
+
- auto-resume-plan 5 + resume CLI 3 + handoff ν΅ν© + μ±λ₯ 2 + λμ νκ· 7
|
|
62
|
+
- μ±λ₯: --version cold start avg **464 ms** Β· MCP 54 λꡬ **449 ms**
|
|
63
|
+
|
|
64
|
+
### 7. μλ release νλ¦
|
|
65
|
+
- main μλ push **65 λΌμ΄λ μ°μ** (1.9.140~203)
|
|
66
|
+
- npm publish μλ (1.9.178~)
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
## 1.9.202 β 2026-05-22
|
|
71
|
+
|
|
72
|
+
**π CμΆ (곡μ νμ€ μ€ν¬ μλ νμ©) 9.0/10 β 9.5/10 λ³΄κ° β matched skill μ€μΉ μν νμ + leerness skill install-top.**
|
|
73
|
+
|
|
74
|
+
μμ¨ λͺ¨λ 132 λΌμ΄λ. 100% λ§€νΈλ¦μ€ λμ β CμΆ λ§μ§λ§ 0.5 λ³΄κ° (97 β 97.5).
|
|
75
|
+
|
|
76
|
+
### 1. install μ΄λ ₯ κΈ°λ‘ + μ€μΉ μν νμ
|
|
77
|
+
- `.harness/skill-installed-log.json` (λΉμν¬λ¦Ώ, 체ν¬μΈ κ°λ₯)
|
|
78
|
+
- ν¨μ: `_loadSkillInstalledLog` / `_appendSkillInstalledLog` / `_isSkillInstalled`
|
|
79
|
+
- handoff matched entry μ `β μ€μΉλ¨` λλ `π` νκ·Έ μλ νμ
|
|
80
|
+
|
|
81
|
+
### 2. `leerness skill install-top` μ κ· CLI
|
|
82
|
+
- handoff 컨ν
μ€νΈ (in-progress task) μ keyword λ‘ official skill λ§€μΉ
|
|
83
|
+
- top 1 (μ΄λ―Έ μ€μΉλ κ² μλ skip) μ¦μ download + install
|
|
84
|
+
- μ€μΉ ν μλ μ΄λ ₯ κΈ°λ‘ β μ€λ³΅ install λ°©μ§
|
|
85
|
+
- `--force`: μ΄λ―Έ μ€μΉλ κ² κ°μ μ¬μ€μΉ
|
|
86
|
+
|
|
87
|
+
### 3. handoff body ν΅ν©
|
|
88
|
+
```
|
|
89
|
+
## π 곡μ organization μ€ν¬ μλ λ§€μΉ (1.9.192/193) β ν€μλ "X"
|
|
90
|
+
β μ€μΉλ¨ [vercel] skill-A β ...
|
|
91
|
+
π [anthropic] skill-B β ...
|
|
92
|
+
β 1κ° μ¦μ: leerness skill install-top (1.9.202)
|
|
93
|
+
β μ 체 μ€μΉ: leerness skill auto-install --yes
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### 4. λμ νκ· (1.9.196~201) β λͺ¨λ μ μ§
|
|
97
|
+
|
|
98
|
+
### 5. stress-v147 β 15/15 PASS
|
|
99
|
+
- μ€μΉ μ΄λ ₯ (6) + μ±λ₯ (2) + λμ νκ· (7)
|
|
100
|
+
- μ±λ₯: --version cold start avg **457 ms** Β· MCP 54 λꡬ **468 ms**
|
|
101
|
+
|
|
102
|
+
### 6. 5μΆ λ§€νΈλ¦μ€
|
|
103
|
+
| μΆ | 1.9.201 | 1.9.202 | μν |
|
|
104
|
+
|---|---|---|---|
|
|
105
|
+
| C. 곡μ νμ€ μ€ν¬ μλ νμ© | 9.0 | **9.5** | +0.5 (μ€μΉ μν + install-top) |
|
|
106
|
+
| **μ’
ν©** | 48.5/50 (97%) | **49/50 (98%)** | **+1%** |
|
|
107
|
+
|
|
108
|
+
### 7. μλ release
|
|
109
|
+
- main μλ push **64 λΌμ΄λ μ°μ** (1.9.140~202)
|
|
110
|
+
- npm publish μλ (1.9.178~)
|
|
111
|
+
|
|
112
|
+
---
|
|
113
|
+
|
|
3
114
|
## 1.9.201 β 2026-05-22
|
|
4
115
|
|
|
5
116
|
**π― EμΆ (κ²μΌλ¦ λ°©μ§) 9.5/10 β 10/10 λ³΄κ° β next-action queue + leerness next-action take λͺ
λ Ή.**
|
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.203 AI Agent Reliability Harness + Sandbox β
|
|
16
16
|
β verify Β· remember Β· orchestrate Β· audit Β· sandbox Β· drift β
|
|
17
|
-
β
|
|
17
|
+
β π auto-resume-plan + leerness resume Β· μμ¨ cycle μμ± β
|
|
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.203';
|
|
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 μ²λ¦¬).
|
|
@@ -1556,6 +1556,77 @@ async function skillDiscoverCmd(root) {
|
|
|
1556
1556
|
log(`π‘ μ€μΉ: leerness skill install <url>`);
|
|
1557
1557
|
}
|
|
1558
1558
|
|
|
1559
|
+
// 1.9.202: CμΆ (곡μ νμ€ μ€ν¬ μλ νμ©) 9.0β9.5 λ³΄κ° β install μ΄λ ₯ κΈ°λ‘ + μ€μΉ μν νμ
|
|
1560
|
+
// 1.9.192 official catalog λ§€μΉ μ "μ΄λ―Έ μ€μΉλ¨" / "μ κ·" κ΅¬λΆ β μ€λ³΅ install λ°©μ§ + μ¬μ©μ μΈμ§ λμ
|
|
1561
|
+
// νμΌ: .harness/skill-installed-log.json (λΉμν¬λ¦Ώ)
|
|
1562
|
+
function _skillInstalledLogPath(root) { return path.join(root, '.harness', 'skill-installed-log.json'); }
|
|
1563
|
+
function _loadSkillInstalledLog(root) {
|
|
1564
|
+
try {
|
|
1565
|
+
const fp = _skillInstalledLogPath(root);
|
|
1566
|
+
if (!exists(fp)) return { installed: [] };
|
|
1567
|
+
const j = JSON.parse(read(fp));
|
|
1568
|
+
return { installed: Array.isArray(j.installed) ? j.installed : [] };
|
|
1569
|
+
} catch { return { installed: [] }; }
|
|
1570
|
+
}
|
|
1571
|
+
function _appendSkillInstalledLog(root, entry) {
|
|
1572
|
+
try {
|
|
1573
|
+
const state = _loadSkillInstalledLog(root);
|
|
1574
|
+
const e = { name: entry.name, source: entry.source || entry.preset || '?', url: entry.url || '', at: new Date().toISOString() };
|
|
1575
|
+
// μ€λ³΅ (κ°μ name + source) μ κ±° ν append
|
|
1576
|
+
state.installed = state.installed.filter(x => !(x.name === e.name && x.source === e.source));
|
|
1577
|
+
state.installed.push(e);
|
|
1578
|
+
mkdirp(path.join(root, '.harness'));
|
|
1579
|
+
writeUtf8(_skillInstalledLogPath(root), JSON.stringify({ installed: state.installed }, null, 2));
|
|
1580
|
+
return true;
|
|
1581
|
+
} catch { return false; }
|
|
1582
|
+
}
|
|
1583
|
+
function _isSkillInstalled(root, entry) {
|
|
1584
|
+
try {
|
|
1585
|
+
const state = _loadSkillInstalledLog(root);
|
|
1586
|
+
const src = entry.source || entry.preset || '?';
|
|
1587
|
+
return state.installed.some(x => x.name === entry.name && x.source === src);
|
|
1588
|
+
} catch { return false; }
|
|
1589
|
+
}
|
|
1590
|
+
|
|
1591
|
+
// 1.9.202: leerness skill install-top β handoff matched μ top 1 entry λ₯Ό μ¦μ install
|
|
1592
|
+
async function skillInstallTopCmd(root) {
|
|
1593
|
+
root = absRoot(root);
|
|
1594
|
+
// handoff context μ keyword μΆμΆ
|
|
1595
|
+
const rows = readProgressRows(root);
|
|
1596
|
+
const active = rows.find(r => r.status === 'in-progress' || r.status === '[μ§ν]') || rows[rows.length - 1];
|
|
1597
|
+
if (!active || !active.request) { fail('in-progress task μμ β leerness handoff . λ¨Όμ '); return process.exit(1); }
|
|
1598
|
+
const m = _matchOfficialSkillsFromCache(root, active.request, 3);
|
|
1599
|
+
if (m.entries.length === 0) {
|
|
1600
|
+
fail(`λ§€μΉλ official skill μμ (keyword: "${(active.request || '').slice(0, 40)}", cache total: ${m.cacheTotal || 0})`);
|
|
1601
|
+
return process.exit(1);
|
|
1602
|
+
}
|
|
1603
|
+
// μ΄λ―Έ μ€μΉλ κ² skip
|
|
1604
|
+
const candidates = m.entries.filter(e => !_isSkillInstalled(root, e));
|
|
1605
|
+
if (candidates.length === 0) {
|
|
1606
|
+
log(`β λͺ¨λ λ§€μΉλ skill μ΄λ―Έ μ€μΉλ¨ (1.9.202 log κΈ°μ€):`);
|
|
1607
|
+
for (const e of m.entries) log(` β’ ${e.name} (${e.preset || e.source}) β μ΄λ―Έ μ€μΉ`);
|
|
1608
|
+
log(` β leerness skill install-top --force λ‘ μ¬μ€μΉ`);
|
|
1609
|
+
return;
|
|
1610
|
+
}
|
|
1611
|
+
const top = has('--force') ? m.entries[0] : candidates[0];
|
|
1612
|
+
log(`# leerness skill install-top (1.9.202 CμΆ λ³΄κ°)`);
|
|
1613
|
+
log(` task: ${(active.request || '').slice(0, 80)}`);
|
|
1614
|
+
log(` λ§€μΉ: ${m.total}/${m.cacheTotal}건 Β· top 1 β ${top.name} (${top.preset || top.source})`);
|
|
1615
|
+
log(` URL: ${top.url || '(none)'}`);
|
|
1616
|
+
log('');
|
|
1617
|
+
if (!top.url) { fail(`top entry url λΆμ¬ β install λΆκ°`); return process.exit(1); }
|
|
1618
|
+
try {
|
|
1619
|
+
log(`π₯ install μμ...`);
|
|
1620
|
+
await skillInstallCmd(root, top.url);
|
|
1621
|
+
_appendSkillInstalledLog(root, top);
|
|
1622
|
+
log('');
|
|
1623
|
+
log(`β μ€μΉ + μ΄λ ₯ κΈ°λ‘ μλ£ (.harness/skill-installed-log.json)`);
|
|
1624
|
+
} catch (e) {
|
|
1625
|
+
fail(`install μ€ν¨: ${e.message}`);
|
|
1626
|
+
return process.exit(1);
|
|
1627
|
+
}
|
|
1628
|
+
}
|
|
1629
|
+
|
|
1559
1630
|
// 1.9.182: skill auto-install β 곡μ organization catalog μλ νμ β skill match β μλ install.
|
|
1560
1631
|
// μ¬μ©μ λͺ
μ: "μ€ν¬μ μ¬μ©νκ±°λ μ μ©ν΄λλ©΄ μ’μ λΆλΆλ€μ μμμ μΉμμ 곡μ μ‘°μ§μ μ€ν¬ λͺ¨μμ νμν΄μ λ€μ΄λ‘λ λ°μμ μ¬μ©"
|
|
1561
1632
|
// μ μ±
: LEERNESS_SKILL_AUTO_INSTALL=1 μΌ λλ§ μ€μ install (보μ opt-in). λ―Έμ€μ μ dry-run (μΆμ²λ§).
|
|
@@ -1662,6 +1733,115 @@ async function skillAutoCacheCmd(root, sub) {
|
|
|
1662
1733
|
if (c.expired) log(` β κ°±μ : leerness skill auto-cache refresh`);
|
|
1663
1734
|
}
|
|
1664
1735
|
|
|
1736
|
+
// 1.9.203: μλ λΌμ΄λ plan μ 리 β μ¬μ©μ λͺ
μ
|
|
1737
|
+
// "λ°±κ·ΈλΌμ΄λμ λ€μ μμ
μ΄ μμκ°λ₯ν μμ μκ° + μΌμ΄λ¬μλ ν΄μΌνλ μΌμ μ 리"
|
|
1738
|
+
// λΌμ΄λ λ§λ¬΄λ¦¬ μ .harness/auto-resume-plan.json μλ μ μ₯ β λ€μ wakeup μ μ¦μ μ€ν κ°λ₯
|
|
1739
|
+
// plan ꡬ쑰: { savedAt, nextRoundVersion, expectedFireAt, focus, contextSnapshot, nextActions }
|
|
1740
|
+
function _autoResumePlanPath(root) { return path.join(root, '.harness', 'auto-resume-plan.json'); }
|
|
1741
|
+
function _loadAutoResumePlan(root) {
|
|
1742
|
+
try {
|
|
1743
|
+
const fp = _autoResumePlanPath(root);
|
|
1744
|
+
if (!exists(fp)) return null;
|
|
1745
|
+
const j = JSON.parse(read(fp));
|
|
1746
|
+
if (!j.savedAt) return null;
|
|
1747
|
+
const ageMs = Date.now() - new Date(j.savedAt).getTime();
|
|
1748
|
+
const expiredMs = j.expectedFireAt ? Date.now() - new Date(j.expectedFireAt).getTime() : 0;
|
|
1749
|
+
return { ...j, ageMs, ageMin: Math.floor(ageMs / 60000), elapsedFromExpected: Math.floor(expiredMs / 60000) };
|
|
1750
|
+
} catch { return null; }
|
|
1751
|
+
}
|
|
1752
|
+
function _writeAutoResumePlan(root, plan) {
|
|
1753
|
+
try {
|
|
1754
|
+
mkdirp(path.join(root, '.harness'));
|
|
1755
|
+
const payload = { savedAt: new Date().toISOString(), ...plan };
|
|
1756
|
+
writeUtf8(_autoResumePlanPath(root), JSON.stringify(payload, null, 2));
|
|
1757
|
+
return true;
|
|
1758
|
+
} catch { return false; }
|
|
1759
|
+
}
|
|
1760
|
+
// νμ¬ μν¬μ€νμ΄μ€ μνμμ λ€μ λΌμ΄λ plan μλ μμ± (νμ¬ task / matrix / handoff gap / next-action queue κ²°ν©)
|
|
1761
|
+
function _buildAutoResumePlan(root, opts) {
|
|
1762
|
+
opts = opts || {};
|
|
1763
|
+
const intervalMin = opts.intervalMin || 25; // R-0001 μꡬ λ£°
|
|
1764
|
+
const now = Date.now();
|
|
1765
|
+
const expectedFireAt = new Date(now + intervalMin * 60 * 1000).toISOString();
|
|
1766
|
+
// νμ¬ in-progress task
|
|
1767
|
+
const rows = readProgressRows(root);
|
|
1768
|
+
const active = rows.find(r => r.status === 'in-progress' || r.status === '[μ§ν]');
|
|
1769
|
+
// νμ¬ VERSION
|
|
1770
|
+
const currentVersion = VERSION;
|
|
1771
|
+
// next-action queue snapshot
|
|
1772
|
+
const queueState = _loadNextActionQueue(root);
|
|
1773
|
+
const queueTop = queueState.queue.length > 0 ? queueState.queue[queueState.queue.length - 1] : null;
|
|
1774
|
+
// memory surface counts
|
|
1775
|
+
const memorySurface = {
|
|
1776
|
+
tasksInProgress: rows.filter(r => r.status === 'in-progress').length,
|
|
1777
|
+
decisions: exists(decisionsPath(root)) ? (read(decisionsPath(root)).match(/^### \d{4}-\d{2}-\d{2}/gm) || []).length : 0,
|
|
1778
|
+
rulesActive: readRules(root).filter(r => r.status === 'active').length,
|
|
1779
|
+
lessons: exists(lessonsPath(root)) ? (read(lessonsPath(root)).match(/^### \d{4}-\d{2}-\d{2}/gm) || []).length : 0
|
|
1780
|
+
};
|
|
1781
|
+
return {
|
|
1782
|
+
nextRoundVersion: opts.nextRoundVersion || `next after ${currentVersion}`,
|
|
1783
|
+
expectedFireAt,
|
|
1784
|
+
intervalMin,
|
|
1785
|
+
focus: opts.focus || (active ? `${active.id} β ${(active.request || '').slice(0, 80)}` : 'μ¬μ©μ λͺ
μ λκΈ° λλ 5μΆ λ§€νΈλ¦μ€ 보κ°'),
|
|
1786
|
+
contextSnapshot: {
|
|
1787
|
+
currentVersion,
|
|
1788
|
+
activeTaskId: active ? active.id : null,
|
|
1789
|
+
activeTaskRequest: active ? (active.request || '').slice(0, 200) : null,
|
|
1790
|
+
memorySurface,
|
|
1791
|
+
r0001Rule: '25λΆ κ°κ²© (μ¬μ©μ λͺ
μ, R-0001)'
|
|
1792
|
+
},
|
|
1793
|
+
nextActions: (queueState.queue || []).slice(-3).map(a => ({ icon: a.icon, title: a.title, command: a.command || null })),
|
|
1794
|
+
note: opts.note || 'λ€μ wakeup μ leerness resume λλ leerness handoff μ€ν β plan μλ μ μ©'
|
|
1795
|
+
};
|
|
1796
|
+
}
|
|
1797
|
+
|
|
1798
|
+
// 1.9.203: leerness resume μ κ· CLI β auto-resume-plan μ½κ³ μ¦μ μ§νν μΌ μλ΄
|
|
1799
|
+
function resumeCmd(root) {
|
|
1800
|
+
root = absRoot(root);
|
|
1801
|
+
const plan = _loadAutoResumePlan(root);
|
|
1802
|
+
if (!plan) {
|
|
1803
|
+
log(`# leerness resume (1.9.203)`);
|
|
1804
|
+
log(` (auto-resume-plan μμ β 첫 λΌμ΄λ)`);
|
|
1805
|
+
log(` β leerness handoff . λ‘ μμ`);
|
|
1806
|
+
return;
|
|
1807
|
+
}
|
|
1808
|
+
if (has('--json')) { log(JSON.stringify(plan, null, 2)); return; }
|
|
1809
|
+
const isTty = process.stdout && process.stdout.isTTY;
|
|
1810
|
+
const cyan = s => isTty ? `\x1b[36m${s}\x1b[0m` : s;
|
|
1811
|
+
const grn = s => isTty ? `\x1b[32m${s}\x1b[0m` : s;
|
|
1812
|
+
const yel = s => isTty ? `\x1b[33m${s}\x1b[0m` : s;
|
|
1813
|
+
const dim = s => isTty ? `\x1b[2m${s}\x1b[0m` : s;
|
|
1814
|
+
log(cyan(`# π leerness resume (1.9.203 μλ λΌμ΄λ plan μ μ©)`));
|
|
1815
|
+
log('');
|
|
1816
|
+
log(` π
plan μ μ₯: ${plan.savedAt} (${plan.ageMin}λΆ μ )`);
|
|
1817
|
+
log(` β° μμ fire: ${plan.expectedFireAt}` + (plan.elapsedFromExpected > 0 ? yel(` (${plan.elapsedFromExpected}λΆ μ§μ°)`) : ' (μ μ)'));
|
|
1818
|
+
log(` π― focus: ${plan.focus}`);
|
|
1819
|
+
log('');
|
|
1820
|
+
log(grn(`## λ€μ λΌμ΄λ: ${plan.nextRoundVersion}`));
|
|
1821
|
+
if (plan.contextSnapshot) {
|
|
1822
|
+
const c = plan.contextSnapshot;
|
|
1823
|
+
log(` νμ¬ λ²μ : ${c.currentVersion}`);
|
|
1824
|
+
if (c.activeTaskId) log(` νμ± task: ${c.activeTaskId} β ${(c.activeTaskRequest || '').slice(0, 70)}`);
|
|
1825
|
+
const m = c.memorySurface || {};
|
|
1826
|
+
log(` memory: T${m.tasksInProgress || 0}/D${m.decisions || 0}/R${m.rulesActive || 0}/L${m.lessons || 0}`);
|
|
1827
|
+
log(` λ£°: ${c.r0001Rule || '-'}`);
|
|
1828
|
+
}
|
|
1829
|
+
if (plan.nextActions && plan.nextActions.length > 0) {
|
|
1830
|
+
log('');
|
|
1831
|
+
log(grn(`## μ¬μ μ 리λ next-actions (${plan.nextActions.length}건)`));
|
|
1832
|
+
for (const a of plan.nextActions) {
|
|
1833
|
+
log(` ${a.icon || 'β’'} ${a.title}`);
|
|
1834
|
+
if (a.command) log(dim(` \`${a.command}\``));
|
|
1835
|
+
}
|
|
1836
|
+
log('');
|
|
1837
|
+
log(dim(` β μ¦μ task μΆκ°: leerness next-action take`));
|
|
1838
|
+
}
|
|
1839
|
+
log('');
|
|
1840
|
+
log(dim(plan.note || ''));
|
|
1841
|
+
log('');
|
|
1842
|
+
log(grn(`β resume μ€λΉ μλ£ β κΆμ₯: leerness handoff . λλ leerness next-action take`));
|
|
1843
|
+
}
|
|
1844
|
+
|
|
1665
1845
|
// 1.9.199: wakeup miss μλ ν볡 κ°ν β last-handoff timestamp κΈ°λ‘ + 25min κΈ°λ interval μ λ° μΈ‘μ
|
|
1666
1846
|
// μ¬μ©μ λͺ
μ (1.9.198 νμ): "22:01μ λΌμ΄λμ μλμ§μ
λμ§μμμ΄"
|
|
1667
1847
|
// 1.9.196 task-log mtime κΈ°λ° detector λ task-log κ° μμ£Ό μ μ
λ°μ΄νΈλλ©΄ false positive.
|
|
@@ -3464,6 +3644,9 @@ function handoff(root) {
|
|
|
3464
3644
|
let _priorHandoffGap = { hasLast: false };
|
|
3465
3645
|
try { _priorHandoffGap = _getLastHandoffGap(root); } catch {}
|
|
3466
3646
|
try { _recordLastHandoff(root); } catch {}
|
|
3647
|
+
// 1.9.203: auto-resume-plan μλ λ‘λ (μ¬μ©μ λͺ
μ β μλ λͺ¨λ μλ νΈλ¦¬κ±°)
|
|
3648
|
+
let _autoResumePlan = null;
|
|
3649
|
+
try { _autoResumePlan = _loadAutoResumePlan(root); } catch {}
|
|
3467
3650
|
// 1.9.96: --json μ΅μ
(ꡬ쑰ν μΆλ ₯, MCP ν΅ν© / μΈλΆ AI μΉν)
|
|
3468
3651
|
if (has('--json')) {
|
|
3469
3652
|
const result = {
|
|
@@ -3835,10 +4018,14 @@ function handoff(root) {
|
|
|
3835
4018
|
log(cyan(`## π 곡μ organization μ€ν¬ μλ λ§€μΉ (1.9.192/193) β ν€μλ "${keyword}"`));
|
|
3836
4019
|
const ageLabel = veryStale ? yel(`${cacheAge} β 7μΌ+`) : (ofm.expired ? yel(`${cacheAge} β λ§λ£`) : `${cacheAge} β`);
|
|
3837
4020
|
log(dim(` vercel-labs/anthropics λ± catalog μΊμ ${ageLabel} Β· ${ofm.total}/${ofm.cacheTotal}건 λ§€μΉ`));
|
|
4021
|
+
// 1.9.202: κ° entry μ μ€μΉ μν νμ (installed/new)
|
|
3838
4022
|
for (const e of ofm.entries) {
|
|
3839
|
-
|
|
4023
|
+
const installed = _isSkillInstalled(root, e);
|
|
4024
|
+
const tag = installed ? 'β μ€μΉλ¨' : 'π';
|
|
4025
|
+
log(dim(` ${tag} [${e.preset || e.source || '?'}] ${e.name} β ${(e.description || '').slice(0, 65)}`));
|
|
3840
4026
|
}
|
|
3841
|
-
log(dim(` β
|
|
4027
|
+
log(dim(` β 1κ° μ¦μ: leerness skill install-top (1.9.202)`));
|
|
4028
|
+
log(dim(` β μ 체 μ€μΉ: leerness skill auto-install --yes`));
|
|
3842
4029
|
if (ofm.expired || veryStale) log(yel(` β κ°±μ κΆμ₯: leerness skill auto-cache refresh (1.9.193 ${veryStale ? '7μΌ+ stale' : '24h+ expired'})`));
|
|
3843
4030
|
log('');
|
|
3844
4031
|
} else if (ofm.cacheTotal === 0) {
|
|
@@ -3974,6 +4161,26 @@ function handoff(root) {
|
|
|
3974
4161
|
}
|
|
3975
4162
|
} catch {}
|
|
3976
4163
|
}
|
|
4164
|
+
// 1.9.203: auto-resume-plan μλ¦Ό β λΌμ΄λ λ§λ¬΄λ¦¬ μ μ μ₯λ plan μλ λ
ΈμΆ
|
|
4165
|
+
// μ¬μ©μ λͺ
μ: "λ°±κ·ΈλΌμ΄λμ λ€μ μμ
μ΄ μμκ°λ₯ν μμ μκ° + μΌμ΄λ¬μλ ν΄μΌνλ μΌμ μ 리"
|
|
4166
|
+
if (_autoResumePlan && !has('--quiet') && process.env.LEERNESS_NO_RESUME_PLAN !== '1') {
|
|
4167
|
+
try {
|
|
4168
|
+
const isTty = process.stdout && process.stdout.isTTY;
|
|
4169
|
+
const cy = s => isTty ? `\x1b[36m${s}\x1b[0m` : s;
|
|
4170
|
+
const dim = s => isTty ? `\x1b[2m${s}\x1b[0m` : s;
|
|
4171
|
+
const yel = s => isTty ? `\x1b[33m${s}\x1b[0m` : s;
|
|
4172
|
+
const elapsed = _autoResumePlan.elapsedFromExpected || 0;
|
|
4173
|
+
const status = elapsed > 5 ? yel(`(${elapsed}λΆ μ§μ°)`) : (elapsed > -5 ? '(μ μ)' : dim(`(${Math.abs(elapsed)}λΆ μΌμ°)`));
|
|
4174
|
+
log(cy(`## π auto-resume-plan λ‘λ (1.9.203) β ${_autoResumePlan.ageMin}λΆ μ μ μ₯ ${status}`));
|
|
4175
|
+
log(dim(` π― focus: ${_autoResumePlan.focus || '(none)'}`));
|
|
4176
|
+
log(dim(` π¦ λ€μ λ²μ : ${_autoResumePlan.nextRoundVersion || '(none)'}`));
|
|
4177
|
+
if (_autoResumePlan.nextActions && _autoResumePlan.nextActions.length > 0) {
|
|
4178
|
+
log(dim(` π₯ μ¬μ μ 리λ actions: ${_autoResumePlan.nextActions.length}건 β leerness next-action take`));
|
|
4179
|
+
}
|
|
4180
|
+
log(dim(` β μμΈ: leerness resume`));
|
|
4181
|
+
log('');
|
|
4182
|
+
} catch {}
|
|
4183
|
+
}
|
|
3977
4184
|
// 1.9.196/199: ScheduleWakeup miss detector β μμ¨ λͺ¨λ μ¬μ©μ λͺ
μ "λͺ»μΌμ΄λλ κ²½μ° μ’
μ’
μμ"
|
|
3978
4185
|
// 1.9.196: task-log mtime κΈ°λ° (60min+) β false positive κ°λ₯
|
|
3979
4186
|
// 1.9.199: last-handoff.json μ λ° μΈ‘μ β R-0001 λ£° (25min) λλΉ gap μΈ‘μ
|
|
@@ -9055,6 +9262,16 @@ function _publishToNpm(root, opts = {}) {
|
|
|
9055
9262
|
if (pubR.status === 0) {
|
|
9056
9263
|
ok(`npm publish μλ£: ${pkgName}@${pkgVersion}`);
|
|
9057
9264
|
try { _recordRun(root, { kind: 'npm_publish', package: pkgName, version: pkgVersion, dryRun: !!opts.dryRun, ok: true }); } catch {}
|
|
9265
|
+
// 1.9.203: λΌμ΄λ λ§λ¬΄λ¦¬ μ λ€μ λΌμ΄λ plan μλ μ μ₯
|
|
9266
|
+
try {
|
|
9267
|
+
const plan = _buildAutoResumePlan(root, {
|
|
9268
|
+
nextRoundVersion: `next after ${pkgVersion}`,
|
|
9269
|
+
focus: 'λ€μ λΌμ΄λ: handoff β next-action take β μ¬μ©μ λͺ
μ λλ 5μΆ λ§€νΈλ¦μ€ 보κ°',
|
|
9270
|
+
intervalMin: 25,
|
|
9271
|
+
note: `λ€μ wakeup μ: 1) leerness resume . μΌλ‘ plan νμΈ 2) leerness handoff . μ€ν 3) leerness next-action take λ‘ μ¦μ task μ§μ
`
|
|
9272
|
+
});
|
|
9273
|
+
_writeAutoResumePlan(root, plan);
|
|
9274
|
+
} catch {}
|
|
9058
9275
|
} else {
|
|
9059
9276
|
const errOut = (pubR.stderr || pubR.stdout || '').slice(-400);
|
|
9060
9277
|
if (/EPUBLISHCONFLICT|already exists|cannot publish over/i.test(errOut)) {
|
|
@@ -14875,6 +15092,8 @@ async function main() {
|
|
|
14875
15092
|
if (cmd === 'skill' && args[1] === 'suggest') return skillSuggestCmd(absRoot(arg('--path', process.cwd())));
|
|
14876
15093
|
// 1.9.182: leerness skill auto-install β 곡μ catalog μλ νμ + skill match λ§€μΉ μ μλ install (μ¬μ©μ λͺ
μ)
|
|
14877
15094
|
if (cmd === 'skill' && args[1] === 'auto-install') return await skillAutoInstallCmd(absRoot(arg('--path', process.cwd())));
|
|
15095
|
+
// 1.9.202: leerness skill install-top β handoff matched top 1 μ¦μ install (CμΆ 9β9.5 보κ°)
|
|
15096
|
+
if (cmd === 'skill' && args[1] === 'install-top') return await skillInstallTopCmd(absRoot(arg('--path', process.cwd())));
|
|
14878
15097
|
// 1.9.192: skill auto-cache β 곡μ organization catalog 24h μΊμ κ΄λ¦¬ (CμΆ λ³΄κ°)
|
|
14879
15098
|
if (cmd === 'skill' && args[1] === 'auto-cache') return await skillAutoCacheCmd(absRoot(arg('--path', process.cwd())), args[2] || 'status');
|
|
14880
15099
|
if (cmd === 'mcp' && args[1] === 'serve') return mcpServeCmd(absRoot(arg('--path', process.cwd())));
|
|
@@ -14888,6 +15107,8 @@ async function main() {
|
|
|
14888
15107
|
if (cmd === 'roadmap') return roadmapCmd(args[1] || process.cwd());
|
|
14889
15108
|
// 1.9.201: next-action queue CLI (EμΆ 9.5β10)
|
|
14890
15109
|
if (cmd === 'next-action') return nextActionCmd(arg('--path', process.cwd()), args[1], ...args.slice(2));
|
|
15110
|
+
// 1.9.203: leerness resume β auto-resume-plan μ½κ³ λ€μ λΌμ΄λ μ¦μ μλ΄ (μ¬μ©μ λͺ
μ)
|
|
15111
|
+
if (cmd === 'resume') return resumeCmd(arg('--path', process.cwd()));
|
|
14891
15112
|
if (cmd === 'rule' && args[1] === 'add') return ruleAdd(arg('--path', process.cwd()), args.slice(2).filter(x => !x.startsWith('-')).join(' '));
|
|
14892
15113
|
if (cmd === 'rule' && args[1] === 'list') return ruleList(arg('--path', process.cwd()));
|
|
14893
15114
|
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.203",
|
|
4
4
|
"description": "Leerness: λΉνκ΄΄ λ§μ΄κ·Έλ μ΄μ
, μλ λ²μ κ°μ§Β·μ
λ°μ΄νΈ, κ³ν/μ§ν/νΈλμ€ν μλν, κ²μΌλ¦Β·μν¬λ¦ΏΒ·μΈμ½λ© μλ κ°λ, Claude Code μ¬λμ ν΅ν©μ κ°μΆ νκ΅μ΄ μ°μ AI κ°λ° νλ€μ€.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"leerness",
|