leerness 1.9.129 β 1.9.130
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 +20 -0
- package/README.md +2 -2
- package/bin/harness.js +62 -2
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,25 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.9.130 β 2026-05-20 π **60 λΌμ΄λ μμ¨ λͺ¨λ λ§μΌμ€ν€**
|
|
4
|
+
|
|
5
|
+
**JSON 4μ’
ν΅ν©μ `memorySurface.archive` νλ μΆκ°** + 60 λΌμ΄λ μμ¨ λμ λ³΄κ³ μ.
|
|
6
|
+
|
|
7
|
+
### Added β archive νλ (JSON 4μ’
)
|
|
8
|
+
- `handoff --json` / `memory status --json` / `session close --json` / `health --json` λͺ¨λ `memorySurface.archive: { decisions, lessons, plan, total }` λ
ΈμΆ
|
|
9
|
+
- `memory status` ν
μ€νΈ λͺ¨λ: `π Archive: D1/L1/P0 (2건)` λΌμΈ μΆκ°
|
|
10
|
+
- μΈλΆ AI κ° ν JSON νΈμΆλ‘ λͺ¨λ λ©λͺ¨λ¦¬ μν (active + archive) λμ νμ
|
|
11
|
+
|
|
12
|
+
### 60 λΌμ΄λ λ§μΌμ€ν€
|
|
13
|
+
- λΌμ΄λ: 60 (1.9.70 β 1.9.130)
|
|
14
|
+
- MCP λꡬ: 11 β **40 π** (1.9.128 λ§μΌμ€ν€)
|
|
15
|
+
- --json λͺ
λ Ή: 6 β **19**
|
|
16
|
+
- handoff μλ νμ: 1 β **7**
|
|
17
|
+
- Memory Surface: WRITE 5 + READ 5 + DELETE 5 + RESTORE 3 + Archive 3
|
|
18
|
+
- stress μλ리μ€: v16 β v74 (58 μΆκ°)
|
|
19
|
+
- e2e: μμ 219/219
|
|
20
|
+
|
|
21
|
+
μμΈ: `_reports/AUTONOMOUS_ROUNDS_60_MILESTONE.md` (λΉκ³΅κ°)
|
|
22
|
+
|
|
3
23
|
## 1.9.129 β 2026-05-20
|
|
4
24
|
|
|
5
25
|
**handoff 7λ²μ§Έ μλ νμ β π μ΅κ·Ό 24h archive μλ¦Ό** β DELETE 5μ’
archive νλμ λ§€ μΈμ
μμ μ μλ λ
ΈμΆ.
|
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) []() []() []() []() []() []() []()
|
|
6
6
|
|
|
7
7
|
```
|
|
8
8
|
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
β βββ ββββββ ββββββ ββββββββββββββββββββββββ ββββββββ β
|
|
13
13
|
β βββββββββββββββββββββββββββ ββββββ ββββββββββββββββββββββ β
|
|
14
14
|
β βββββββββββββββββββββββββββ ββββββ βββββββββββββββββββββ β
|
|
15
|
-
β v1.9.
|
|
15
|
+
β v1.9.130 AI Agent Reliability Harness β
|
|
16
16
|
β verify Β· remember Β· orchestrate Β· audit Β· prevent drift β
|
|
17
17
|
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
18
18
|
```
|
package/bin/harness.js
CHANGED
|
@@ -6,7 +6,7 @@ const path = require('path');
|
|
|
6
6
|
const cp = require('child_process');
|
|
7
7
|
const readline = require('readline');
|
|
8
8
|
|
|
9
|
-
const VERSION = '1.9.
|
|
9
|
+
const VERSION = '1.9.130';
|
|
10
10
|
const MARK = '<!-- leerness:managed -->';
|
|
11
11
|
const README_START = '<!-- leerness:project-readme:start -->';
|
|
12
12
|
const README_END = '<!-- leerness:project-readme:end -->';
|
|
@@ -330,6 +330,7 @@ leerness audit . --fix # λλ½ λ©ν μλ 보κ°
|
|
|
330
330
|
- 1.9.127+ \`leerness memory archive list [--surface decisions|lessons|plan] [--json]\` + MCP **39 λꡬ** (\`leerness_memory_archive_list\`) β DELETE 5μ’
archive ν΅ν© μ‘°ν (볡μ ν보 νμ).
|
|
331
331
|
- 1.9.128+ \`leerness memory restore <surface> <target>\` + MCP **40 λꡬ π** (\`leerness_memory_restore\`) β archive β active λ³΅κ· (DELETEβRESTORE cycle μμ±). **MCP 40 λꡬ λ§μΌμ€ν€**.
|
|
332
332
|
- 1.9.129+ handoff **7λ²μ§Έ μλ νμ** β \`π μ΅κ·Ό 24h archive\` (D/L/P μΉ΄μ΄νΈ + 볡μ ν보 μλ΄). DELETE νλ μλ μΈμ§.
|
|
333
|
+
- 1.9.130+ π **60 λΌμ΄λ μμ¨ λͺ¨λ λ§μΌμ€ν€** β JSON 4μ’
(handoff/memory status/session close/health) \`memorySurface.archive\` νλ ν΅ν©. MCP 40 / handoff auto-recovery 7 / DELETE-RESTORE cycle μμ±.
|
|
333
334
|
|
|
334
335
|
---
|
|
335
336
|
|
|
@@ -1425,6 +1426,19 @@ function memoryStatusCmd(root, opts = {}) {
|
|
|
1425
1426
|
const lm = exists(lessonsPath(root)) ? read(lessonsPath(root)) : '';
|
|
1426
1427
|
const lessonHeaders = lm.match(/^### \d{4}-\d{2}-\d{2}[^\n]*/gm) || [];
|
|
1427
1428
|
const lessonsLatest = lessonHeaders.length ? (lm.split('\n').filter(l => /- Lesson:/.test(l)).pop() || '').replace(/^- Lesson:\s*/, '').slice(0, 100) : null;
|
|
1429
|
+
// 1.9.130: DELETE 5μ’
archive entry counts
|
|
1430
|
+
const archiveCounts = { decisions: 0, lessons: 0, plan: 0, total: 0 };
|
|
1431
|
+
try {
|
|
1432
|
+
const hd = path.join(root, '.harness');
|
|
1433
|
+
for (const [key, file] of [['decisions', 'decisions.archive.md'], ['lessons', 'lessons.archive.md'], ['plan', 'plan.archive.md']]) {
|
|
1434
|
+
const fp = path.join(hd, file);
|
|
1435
|
+
if (exists(fp)) {
|
|
1436
|
+
const entries = _parseArchiveBlocks(read(fp));
|
|
1437
|
+
archiveCounts[key] = entries.length;
|
|
1438
|
+
archiveCounts.total += entries.length;
|
|
1439
|
+
}
|
|
1440
|
+
}
|
|
1441
|
+
} catch {}
|
|
1428
1442
|
|
|
1429
1443
|
const payload = {
|
|
1430
1444
|
version: VERSION,
|
|
@@ -1434,6 +1448,7 @@ function memoryStatusCmd(root, opts = {}) {
|
|
|
1434
1448
|
rules: { active: rulesActive, paused: rulesPaused, total: rules.length },
|
|
1435
1449
|
plan: { milestones, inProgress: planInProgress },
|
|
1436
1450
|
lessons: { count: lessonHeaders.length, latest: lessonsLatest },
|
|
1451
|
+
archive: archiveCounts, // 1.9.130
|
|
1437
1452
|
summary: `T${tasksInProgress}/D${decisionHeaders.length}/R${rulesActive}/P${milestones}/L${lessonHeaders.length}`,
|
|
1438
1453
|
};
|
|
1439
1454
|
if (jsonMode) {
|
|
@@ -1450,6 +1465,7 @@ function memoryStatusCmd(root, opts = {}) {
|
|
|
1450
1465
|
log(`πΊ Plan: ${milestones} milestones (${planInProgress} in-progress)`);
|
|
1451
1466
|
log(`π‘ Lessons: ${lessonHeaders.length} entries`);
|
|
1452
1467
|
if (lessonsLatest) log(` - μ΅κ·Ό: ${lessonsLatest}`);
|
|
1468
|
+
if (archiveCounts.total > 0) log(`π Archive: D${archiveCounts.decisions}/L${archiveCounts.lessons}/P${archiveCounts.plan} (${archiveCounts.total}건)`);
|
|
1453
1469
|
log(`\nπ Summary: ${payload.summary}`);
|
|
1454
1470
|
}
|
|
1455
1471
|
|
|
@@ -2484,12 +2500,26 @@ function handoff(root) {
|
|
|
2484
2500
|
const milestones = (planText.match(/^### M-\d{4}\./gm) || []).length;
|
|
2485
2501
|
const lm = exists(lessonsPath(root)) ? read(lessonsPath(root)) : '';
|
|
2486
2502
|
const lessonsCount = (lm.match(/^### \d{4}-\d{2}-\d{2}[^\n]*/gm) || []).length;
|
|
2503
|
+
// 1.9.130: archive μΉ΄μ΄νΈ ν΅ν©
|
|
2504
|
+
const archiveCountsH = { decisions: 0, lessons: 0, plan: 0, total: 0 };
|
|
2505
|
+
try {
|
|
2506
|
+
const hdH = path.join(root, '.harness');
|
|
2507
|
+
for (const [key, file] of [['decisions', 'decisions.archive.md'], ['lessons', 'lessons.archive.md'], ['plan', 'plan.archive.md']]) {
|
|
2508
|
+
const fpH = path.join(hdH, file);
|
|
2509
|
+
if (exists(fpH)) {
|
|
2510
|
+
const entries = _parseArchiveBlocks(read(fpH));
|
|
2511
|
+
archiveCountsH[key] = entries.length;
|
|
2512
|
+
archiveCountsH.total += entries.length;
|
|
2513
|
+
}
|
|
2514
|
+
}
|
|
2515
|
+
} catch {}
|
|
2487
2516
|
result.memorySurface = {
|
|
2488
2517
|
tasks: { inProgress: tasksInProgress, total: rows.length, byStatus: tasksByStatus },
|
|
2489
2518
|
decisions: { count: decisionsCount },
|
|
2490
2519
|
rules: { active: rulesActive, total: rules.length },
|
|
2491
2520
|
plan: { milestones },
|
|
2492
2521
|
lessons: { count: lessonsCount },
|
|
2522
|
+
archive: archiveCountsH, // 1.9.130
|
|
2493
2523
|
summary: `T${tasksInProgress}/D${decisionsCount}/R${rulesActive}/P${milestones}/L${lessonsCount}`,
|
|
2494
2524
|
};
|
|
2495
2525
|
} catch {}
|
|
@@ -4238,7 +4268,7 @@ function _banner(opts = {}) {
|
|
|
4238
4268
|
lines.push('');
|
|
4239
4269
|
for (const ln of lines) log(ln);
|
|
4240
4270
|
if (opts.quickStart) {
|
|
4241
|
-
log(C.bold(C.cyan(' β¨ λΉ λ₯Έ μμ (1.9.
|
|
4271
|
+
log(C.bold(C.cyan(' β¨ λΉ λ₯Έ μμ (1.9.130+ π 60 λΌμ΄λ λ§μΌμ€ν€ archive νλ ν΅ν© β 60 λΌμ΄λ μμ¨ λμ )')));
|
|
4242
4272
|
log(' ' + C.green('npx leerness@latest init .') + C.dim(' # μ κ· νλ‘μ νΈ + μΈλΆ AI CLI μ€μ '));
|
|
4243
4273
|
log(' ' + C.green('npx leerness handoff .') + C.dim(' # 컨ν
μ€νΈ + lessons + λ§€μΉ skill + history hit + brainstorm hits + ν€λλΌμΈ'));
|
|
4244
4274
|
log(' ' + C.green('npx leerness handoff . --quiet') + C.dim(' # μλν/CI λͺ¨λ (1.9.99) β μλ νμ λΌμΈ λΉνμ±'));
|
|
@@ -5160,12 +5190,26 @@ function sessionClose(root, opts = {}) {
|
|
|
5160
5190
|
const milestones0 = (planText0.match(/^### M-\d{4}\./gm) || []).length;
|
|
5161
5191
|
const lm0 = exists(lessonsPath(root)) ? read(lessonsPath(root)) : '';
|
|
5162
5192
|
const lessonsCount0 = (lm0.match(/^### \d{4}-\d{2}-\d{2}[^\n]*/gm) || []).length;
|
|
5193
|
+
// 1.9.130: archive μΉ΄μ΄νΈ ν΅ν©
|
|
5194
|
+
const archiveCountsS = { decisions: 0, lessons: 0, plan: 0, total: 0 };
|
|
5195
|
+
try {
|
|
5196
|
+
const hdS = path.join(root, '.harness');
|
|
5197
|
+
for (const [key, file] of [['decisions', 'decisions.archive.md'], ['lessons', 'lessons.archive.md'], ['plan', 'plan.archive.md']]) {
|
|
5198
|
+
const fpS = path.join(hdS, file);
|
|
5199
|
+
if (exists(fpS)) {
|
|
5200
|
+
const entries = _parseArchiveBlocks(read(fpS));
|
|
5201
|
+
archiveCountsS[key] = entries.length;
|
|
5202
|
+
archiveCountsS.total += entries.length;
|
|
5203
|
+
}
|
|
5204
|
+
}
|
|
5205
|
+
} catch {}
|
|
5163
5206
|
jsonResult.memorySurface = {
|
|
5164
5207
|
tasks: { inProgress: tasksInProgress0, total: rows0.length, byStatus: tasksByStatus0 },
|
|
5165
5208
|
decisions: { count: decisionsCount0 },
|
|
5166
5209
|
rules: { active: rulesActive0, total: rules0.length },
|
|
5167
5210
|
plan: { milestones: milestones0 },
|
|
5168
5211
|
lessons: { count: lessonsCount0 },
|
|
5212
|
+
archive: archiveCountsS, // 1.9.130
|
|
5169
5213
|
summary: `T${tasksInProgress0}/D${decisionsCount0}/R${rulesActive0}/P${milestones0}/L${lessonsCount0}`,
|
|
5170
5214
|
};
|
|
5171
5215
|
} catch {}
|
|
@@ -8777,6 +8821,22 @@ function healthCmd(root) {
|
|
|
8777
8821
|
rules: { active: rulesActive, total: rules.length },
|
|
8778
8822
|
plan: { milestones },
|
|
8779
8823
|
lessons: { count: lessonsCount },
|
|
8824
|
+
archive: (() => {
|
|
8825
|
+
// 1.9.130: archive μΉ΄μ΄νΈ ν΅ν©
|
|
8826
|
+
const a = { decisions: 0, lessons: 0, plan: 0, total: 0 };
|
|
8827
|
+
try {
|
|
8828
|
+
const hdHe = path.join(root, '.harness');
|
|
8829
|
+
for (const [key, file] of [['decisions', 'decisions.archive.md'], ['lessons', 'lessons.archive.md'], ['plan', 'plan.archive.md']]) {
|
|
8830
|
+
const fpHe = path.join(hdHe, file);
|
|
8831
|
+
if (exists(fpHe)) {
|
|
8832
|
+
const entries = _parseArchiveBlocks(read(fpHe));
|
|
8833
|
+
a[key] = entries.length;
|
|
8834
|
+
a.total += entries.length;
|
|
8835
|
+
}
|
|
8836
|
+
}
|
|
8837
|
+
} catch {}
|
|
8838
|
+
return a;
|
|
8839
|
+
})(),
|
|
8780
8840
|
summary: `T${tasksInProgress}/D${decisionsCount}/R${rulesActive}/P${milestones}/L${lessonsCount}`,
|
|
8781
8841
|
};
|
|
8782
8842
|
} catch { out.memorySurface = { error: 'memorySurface μ κ² μ€ν¨' }; }
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "leerness",
|
|
3
|
-
"version": "1.9.
|
|
3
|
+
"version": "1.9.130",
|
|
4
4
|
"description": "Leerness: λΉνκ΄΄ λ§μ΄κ·Έλ μ΄μ
, μλ λ²μ κ°μ§Β·μ
λ°μ΄νΈ, κ³ν/μ§ν/νΈλμ€ν μλν, κ²μΌλ¦Β·μν¬λ¦ΏΒ·μΈμ½λ© μλ κ°λ, Claude Code μ¬λμ ν΅ν©μ κ°μΆ νκ΅μ΄ μ°μ AI κ°λ° νλ€μ€.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"leerness",
|