leerness 1.9.137 → 1.9.139
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 +51 -0
- package/README.md +2 -2
- package/bin/harness.js +60 -23
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,56 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.9.139 — 2026-05-20
|
|
4
|
+
|
|
5
|
+
**`leerness lesson list --query <keyword>` + `leerness decision list --query <keyword>` 필터 추가** — Memory Surface READ 명령 키워드 검색.
|
|
6
|
+
|
|
7
|
+
### Added — --query 필터
|
|
8
|
+
- `lesson list --query` — text/tag case-insensitive 매칭
|
|
9
|
+
- `decision list --query` — title/decision/reason/alternatives/impact 매칭
|
|
10
|
+
- 정규식 특수문자 자동 escape
|
|
11
|
+
- JSON 응답 `query` 필드, 텍스트 모드 헤더 표시
|
|
12
|
+
|
|
13
|
+
### Updated MCP
|
|
14
|
+
- `leerness_lesson_list` 인자에 `query` 추가
|
|
15
|
+
- `leerness_decision_list` 인자에 `query` 추가
|
|
16
|
+
|
|
17
|
+
### 사용 시나리오
|
|
18
|
+
```bash
|
|
19
|
+
leerness decision list --query PostgreSQL --json
|
|
20
|
+
leerness lesson list --query auth --json
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
### --query 필터 매트릭스 (1.9.139)
|
|
24
|
+
| 명령 | --query 도입 |
|
|
25
|
+
|---|---|
|
|
26
|
+
| `memory archive list` | 1.9.138 |
|
|
27
|
+
| `lesson list` | **1.9.139** |
|
|
28
|
+
| `decision list` | **1.9.139** |
|
|
29
|
+
| `task list` | (--status 필터만) |
|
|
30
|
+
| `plan list` | (필터 없음, 미래 후보) |
|
|
31
|
+
| `rule list` | (필터 없음, 미래 후보) |
|
|
32
|
+
|
|
33
|
+
## 1.9.138 — 2026-05-20
|
|
34
|
+
|
|
35
|
+
**`leerness memory archive list --query <keyword>` 필터 추가** — archive 항목 키워드 검색.
|
|
36
|
+
|
|
37
|
+
### Added — --query 필터
|
|
38
|
+
- `target` 또는 `originalHeader` 에 키워드 case-insensitive 매칭
|
|
39
|
+
- 정규식 특수문자는 자동 escape
|
|
40
|
+
- 텍스트 모드 헤더에 `— query: "..."` 표시
|
|
41
|
+
- JSON 모드 응답에 `query` 필드 추가
|
|
42
|
+
- 매칭 0건 시 안내 메시지
|
|
43
|
+
|
|
44
|
+
### Updated — MCP leerness_memory_archive_list
|
|
45
|
+
- 신규 인자: `{ query? }` (optional)
|
|
46
|
+
- 외부 AI 가 archive 에서 특정 주제 항목만 회수 가능
|
|
47
|
+
|
|
48
|
+
### 사용 시나리오
|
|
49
|
+
```
|
|
50
|
+
leerness memory archive list --query PostgreSQL --json
|
|
51
|
+
# → decisions/lessons/plan 중 PostgreSQL 매칭만 반환
|
|
52
|
+
```
|
|
53
|
+
|
|
3
54
|
## 1.9.137 — 2026-05-20
|
|
4
55
|
|
|
5
56
|
**`.harness/session-workflow.md` 템플릿 갱신 — Memory CRUD Quick Reference 추가** — 신규 \`init\` 워크스페이스의 AI 에이전트에 5 surface CRUD 매트릭스 + archive cycle 가이드 제공.
|
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.139 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.139';
|
|
10
10
|
const MARK = '<!-- leerness:managed -->';
|
|
11
11
|
const README_START = '<!-- leerness:project-readme:start -->';
|
|
12
12
|
const README_END = '<!-- leerness:project-readme:end -->';
|
|
@@ -363,6 +363,8 @@ leerness memory restore <surface> <target> # archive → active 복귀 (DELETE
|
|
|
363
363
|
- 1.9.135+ MCP **42 도구** (\`leerness_rule_remove\`) — rules.md 에서 특정 rule 제거 + archive 보존. **5 surface CRUD MCP 완전 완성** (task/decision/lesson/plan/rule 모두 add/list/delete MCP 노출).
|
|
364
364
|
- 1.9.136+ MCP \`leerness_drift_check\` JSON 응답 fix — \`--json\` 플래그 자동 추가하여 외부 AI가 구조화된 drift 신호 회수 (score, level, signals[], healthy).
|
|
365
365
|
- 1.9.137+ \`.harness/session-workflow.md\` 템플릿에 **🧠 Memory CRUD Quick Reference** 섹션 추가 — 5 surface × CRUD 매트릭스 + archive cycle 워크플로 가이드. 신규 \`init\` 워크스페이스 즉시 적용.
|
|
366
|
+
- 1.9.138+ \`leerness memory archive list --query <keyword>\` + MCP \`leerness_memory_archive_list\` query 인자 — archive 항목 키워드 case-insensitive 검색 (target/originalHeader 매칭).
|
|
367
|
+
- 1.9.139+ \`leerness lesson list --query\` + \`leerness decision list --query\` + MCP 동일 인자 — active Memory 항목 키워드 검색 (lesson: text/tag, decision: title/decision/reason/alternatives/impact).
|
|
366
368
|
|
|
367
369
|
---
|
|
368
370
|
|
|
@@ -1547,6 +1549,9 @@ function memoryArchiveListCmd(root, opts = {}) {
|
|
|
1547
1549
|
root = absRoot(root);
|
|
1548
1550
|
const jsonMode = !!opts.json || has('--json');
|
|
1549
1551
|
const surfaceFilter = arg('--surface', '');
|
|
1552
|
+
// 1.9.138: --query 키워드 필터 (target / originalHeader 매칭, case-insensitive)
|
|
1553
|
+
const queryFilter = arg('--query', '');
|
|
1554
|
+
const queryRe = queryFilter ? new RegExp(queryFilter.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'), 'i') : null;
|
|
1550
1555
|
const hd = path.join(root, '.harness');
|
|
1551
1556
|
const archives = {
|
|
1552
1557
|
decisions: { path: path.join(hd, 'decisions.archive.md'), entries: [] },
|
|
@@ -1556,7 +1561,14 @@ function memoryArchiveListCmd(root, opts = {}) {
|
|
|
1556
1561
|
for (const k of Object.keys(archives)) {
|
|
1557
1562
|
if (surfaceFilter && surfaceFilter !== k) continue;
|
|
1558
1563
|
const a = archives[k];
|
|
1559
|
-
if (exists(a.path))
|
|
1564
|
+
if (exists(a.path)) {
|
|
1565
|
+
let entries = _parseArchiveBlocks(read(a.path));
|
|
1566
|
+
// 1.9.138: --query 필터 적용 (target 또는 originalHeader 매칭)
|
|
1567
|
+
if (queryRe) {
|
|
1568
|
+
entries = entries.filter(e => queryRe.test(e.target || '') || queryRe.test(e.originalHeader || ''));
|
|
1569
|
+
}
|
|
1570
|
+
a.entries = entries;
|
|
1571
|
+
}
|
|
1560
1572
|
}
|
|
1561
1573
|
const totals = {
|
|
1562
1574
|
decisions: archives.decisions.entries.length,
|
|
@@ -1572,12 +1584,14 @@ function memoryArchiveListCmd(root, opts = {}) {
|
|
|
1572
1584
|
plan: archives.plan.entries,
|
|
1573
1585
|
totals
|
|
1574
1586
|
};
|
|
1587
|
+
if (queryFilter) payload.query = queryFilter;
|
|
1588
|
+
if (surfaceFilter) payload.surface = surfaceFilter;
|
|
1575
1589
|
process.stdout.write(JSON.stringify(payload, null, 2) + '\n');
|
|
1576
1590
|
return;
|
|
1577
1591
|
}
|
|
1578
|
-
log('# 🗑 Memory Archive List (1.9.127)\n');
|
|
1592
|
+
log('# 🗑 Memory Archive List (1.9.127)' + (queryFilter ? ` — query: "${queryFilter}"` : '') + '\n');
|
|
1579
1593
|
if (totals.all === 0) {
|
|
1580
|
-
log('(archive 파일 없음 — 아직 제거된 항목 없음)');
|
|
1594
|
+
log(queryFilter ? `(매칭 archive entry 없음 — query: "${queryFilter}")` : '(archive 파일 없음 — 아직 제거된 항목 없음)');
|
|
1581
1595
|
return;
|
|
1582
1596
|
}
|
|
1583
1597
|
if ((!surfaceFilter || surfaceFilter === 'decisions') && archives.decisions.entries.length) {
|
|
@@ -1664,10 +1678,15 @@ function lessonListCmd(root, opts = {}) {
|
|
|
1664
1678
|
root = absRoot(root);
|
|
1665
1679
|
const jsonMode = !!opts.json || has('--json');
|
|
1666
1680
|
const tagFilter = arg('--tag', null);
|
|
1681
|
+
// 1.9.139: --query 필터 (lesson text case-insensitive 매칭)
|
|
1682
|
+
const queryFilter = arg('--query', null);
|
|
1683
|
+
const queryRe = queryFilter ? new RegExp(queryFilter.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'), 'i') : null;
|
|
1667
1684
|
const lp = lessonsPath(root);
|
|
1668
1685
|
if (!exists(lp)) {
|
|
1669
1686
|
if (jsonMode) {
|
|
1670
|
-
|
|
1687
|
+
const empty = { version: VERSION, root, total: 0, lessons: [], tag: tagFilter };
|
|
1688
|
+
if (queryFilter) empty.query = queryFilter;
|
|
1689
|
+
process.stdout.write(JSON.stringify(empty, null, 2) + '\n');
|
|
1671
1690
|
return;
|
|
1672
1691
|
}
|
|
1673
1692
|
return ok('lessons.md 없음 — leerness lesson save "<text>" 로 첫 lesson 영구화');
|
|
@@ -1686,19 +1705,24 @@ function lessonListCmd(root, opts = {}) {
|
|
|
1686
1705
|
tag: tagMatch ? tagMatch[1].trim() : null,
|
|
1687
1706
|
};
|
|
1688
1707
|
if (tagFilter && lesson.tag !== tagFilter) continue;
|
|
1708
|
+
// 1.9.139: query 필터 — lesson text 또는 tag 매칭
|
|
1709
|
+
if (queryRe && !queryRe.test(lesson.text) && !queryRe.test(lesson.tag || '')) continue;
|
|
1689
1710
|
lessons.push(lesson);
|
|
1690
1711
|
}
|
|
1691
1712
|
if (jsonMode) {
|
|
1692
|
-
|
|
1713
|
+
const payload = { version: VERSION, root, total: lessons.length, lessons, tag: tagFilter };
|
|
1714
|
+
if (queryFilter) payload.query = queryFilter;
|
|
1715
|
+
process.stdout.write(JSON.stringify(payload, null, 2) + '\n');
|
|
1693
1716
|
return;
|
|
1694
1717
|
}
|
|
1695
|
-
log(`# 💡 Lessons (1.9.117)${tagFilter ? ` — tag: ${tagFilter}` : ''}\n`);
|
|
1718
|
+
log(`# 💡 Lessons (1.9.117)${tagFilter ? ` — tag: ${tagFilter}` : ''}${queryFilter ? ` — query: "${queryFilter}"` : ''}\n`);
|
|
1696
1719
|
if (!lessons.length) {
|
|
1697
|
-
if (
|
|
1720
|
+
if (queryFilter) ok(`"${queryFilter}" 매칭 lesson 없음`);
|
|
1721
|
+
else if (tagFilter) ok(`"${tagFilter}" 태그 lesson 없음`);
|
|
1698
1722
|
else ok('lessons 비어있음');
|
|
1699
1723
|
return;
|
|
1700
1724
|
}
|
|
1701
|
-
log(`총 ${lessons.length}건${tagFilter ? ` (tag: ${tagFilter})` : ''}:`);
|
|
1725
|
+
log(`총 ${lessons.length}건${tagFilter ? ` (tag: ${tagFilter})` : ''}${queryFilter ? ` (query: "${queryFilter}")` : ''}:`);
|
|
1702
1726
|
for (const l of lessons) {
|
|
1703
1727
|
log(`\n[${l.date || '?'}]${l.tag ? ` #${l.tag}` : ''}`);
|
|
1704
1728
|
log(` ${l.text}`);
|
|
@@ -1759,10 +1783,15 @@ function lessonSave(root, text) {
|
|
|
1759
1783
|
function decisionListCmd(root, opts = {}) {
|
|
1760
1784
|
root = absRoot(root);
|
|
1761
1785
|
const jsonMode = !!opts.json || has('--json');
|
|
1786
|
+
// 1.9.139: --query 필터 (title/decision/reason case-insensitive 매칭)
|
|
1787
|
+
const queryFilter = arg('--query', null);
|
|
1788
|
+
const queryRe = queryFilter ? new RegExp(queryFilter.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'), 'i') : null;
|
|
1762
1789
|
const dp = decisionsPath(root);
|
|
1763
1790
|
if (!exists(dp)) {
|
|
1764
1791
|
if (jsonMode) {
|
|
1765
|
-
|
|
1792
|
+
const empty = { version: VERSION, root, total: 0, decisions: [] };
|
|
1793
|
+
if (queryFilter) empty.query = queryFilter;
|
|
1794
|
+
process.stdout.write(JSON.stringify(empty, null, 2) + '\n');
|
|
1766
1795
|
return;
|
|
1767
1796
|
}
|
|
1768
1797
|
return ok('decisions.md 없음 — leerness decision add "<title>" 로 첫 결정 영구화');
|
|
@@ -1782,22 +1811,30 @@ function decisionListCmd(root, opts = {}) {
|
|
|
1782
1811
|
const reasonMatch = block.match(/- Reason:\s*(.+)/);
|
|
1783
1812
|
const alternativesMatch = block.match(/- Alternatives:\s*(.+)/);
|
|
1784
1813
|
const impactMatch = block.match(/- Impact:\s*(.+)/);
|
|
1785
|
-
|
|
1814
|
+
const entry = {
|
|
1786
1815
|
date,
|
|
1787
1816
|
title,
|
|
1788
1817
|
decision: decisionMatch ? decisionMatch[1].trim() : null,
|
|
1789
1818
|
reason: reasonMatch ? reasonMatch[1].trim() : null,
|
|
1790
1819
|
alternatives: alternativesMatch ? alternativesMatch[1].trim() : null,
|
|
1791
1820
|
impact: impactMatch ? impactMatch[1].trim() : null,
|
|
1792
|
-
}
|
|
1821
|
+
};
|
|
1822
|
+
// 1.9.139: query 필터 — title/decision/reason 매칭
|
|
1823
|
+
if (queryRe) {
|
|
1824
|
+
const hay = [entry.title, entry.decision, entry.reason, entry.alternatives, entry.impact].filter(Boolean).join(' ');
|
|
1825
|
+
if (!queryRe.test(hay)) continue;
|
|
1826
|
+
}
|
|
1827
|
+
decisions.push(entry);
|
|
1793
1828
|
}
|
|
1794
1829
|
if (jsonMode) {
|
|
1795
|
-
|
|
1830
|
+
const payload = { version: VERSION, root, total: decisions.length, decisions };
|
|
1831
|
+
if (queryFilter) payload.query = queryFilter;
|
|
1832
|
+
process.stdout.write(JSON.stringify(payload, null, 2) + '\n');
|
|
1796
1833
|
return;
|
|
1797
1834
|
}
|
|
1798
|
-
log(`# 🧠 Decisions (1.9.118)\n`);
|
|
1799
|
-
if (!decisions.length) return ok('decisions 비어있음');
|
|
1800
|
-
log(`총 ${decisions.length}
|
|
1835
|
+
log(`# 🧠 Decisions (1.9.118)${queryFilter ? ` — query: "${queryFilter}"` : ''}\n`);
|
|
1836
|
+
if (!decisions.length) return ok(queryFilter ? `"${queryFilter}" 매칭 decision 없음` : 'decisions 비어있음');
|
|
1837
|
+
log(`총 ${decisions.length}건${queryFilter ? ` (query: "${queryFilter}")` : ''}:`);
|
|
1801
1838
|
for (const d of decisions) {
|
|
1802
1839
|
log(`\n[${d.date || '?'}] ${d.title}`);
|
|
1803
1840
|
if (d.reason) log(` Reason: ${d.reason}`);
|
|
@@ -4321,7 +4358,7 @@ function _banner(opts = {}) {
|
|
|
4321
4358
|
lines.push('');
|
|
4322
4359
|
for (const ln of lines) log(ln);
|
|
4323
4360
|
if (opts.quickStart) {
|
|
4324
|
-
log(C.bold(C.cyan(' ✨ 빠른 시작 (1.9.
|
|
4361
|
+
log(C.bold(C.cyan(' ✨ 빠른 시작 (1.9.139+ lesson/decision list --query 필터 — 69 라운드 자율 누적)')));
|
|
4325
4362
|
log(' ' + C.green('npx leerness@latest init .') + C.dim(' # 신규 프로젝트 + 외부 AI CLI 설정'));
|
|
4326
4363
|
log(' ' + C.green('npx leerness handoff .') + C.dim(' # 컨텍스트 + lessons + 매칭 skill + history hit + brainstorm hits + 헤드라인'));
|
|
4327
4364
|
log(' ' + C.green('npx leerness handoff . --quiet') + C.dim(' # 자동화/CI 모드 (1.9.99) — 자동 회수 라인 비활성'));
|
|
@@ -8631,13 +8668,13 @@ function mcpServeCmd(root) {
|
|
|
8631
8668
|
{ name: 'leerness_plan_add', description: '1.9.110 — plan.md 에 새 milestone 추가 + progress-tracker.md에 자동 동기화 task 생성. 외부 AI가 계획 단계를 직접 등록. 인자: { text (required), status?, progress?, nextAction?, path? }', inputSchema: { type: 'object', properties: { text: { type: 'string' }, status: { type: 'string' }, progress: { type: 'string' }, nextAction: { type: 'string' }, path: { type: 'string' } }, required: ['text'] } },
|
|
8632
8669
|
{ name: 'leerness_lesson_save', description: '1.9.112 — .harness/lessons.md 에 새 lesson 영구화 (Memory Write Surface 5번째). 외부 AI가 세션 중 얻은 통찰을 즉시 영구 기록 — handoff 자동 회수와 통합. 인자: { text (required), tag?, path? }', inputSchema: { type: 'object', properties: { text: { type: 'string' }, tag: { type: 'string' }, path: { type: 'string' } }, required: ['text'] } },
|
|
8633
8670
|
{ name: 'leerness_memory_status', description: '1.9.114 — Memory Write Surface 5종 (tasks/decisions/rules/plan/lessons) 통합 상태 JSON. 외부 AI가 한 호출로 영구화 상태 + 카운트 + 최근 항목 회수. summary 필드는 "T2/D3/R1/P5/L7" 형식', inputSchema: { type: 'object', properties: { path: { type: 'string' } } } },
|
|
8634
|
-
{ name: 'leerness_lesson_list', description: '1.9.117 — lessons.md 전용 list JSON ({ date, text, tag }[]). --tag 필터 지원. 외부 AI가 영구화된 lesson 전체 회수 (vs leerness_lessons 는 다중 source fuzzy 매칭)', inputSchema: { type: 'object', properties: { path: { type: 'string' }, tag: { type: 'string' } } } },
|
|
8635
|
-
{ name: 'leerness_decision_list', description: '1.9.118 — decisions.md 전체 조회 JSON ({ date, title, decision, reason, alternatives, impact }[]). 외부 AI가 영구화된 설계 결정 전체 회수
|
|
8671
|
+
{ name: 'leerness_lesson_list', description: '1.9.117 — lessons.md 전용 list JSON ({ date, text, tag }[]). --tag 필터 지원. 1.9.139+ --query 키워드 필터 (text/tag case-insensitive). 외부 AI가 영구화된 lesson 전체 회수 (vs leerness_lessons 는 다중 source fuzzy 매칭)', inputSchema: { type: 'object', properties: { path: { type: 'string' }, tag: { type: 'string' }, query: { type: 'string' } } } },
|
|
8672
|
+
{ name: 'leerness_decision_list', description: '1.9.118 — decisions.md 전체 조회 JSON ({ date, title, decision, reason, alternatives, impact }[]). 1.9.139+ --query 키워드 필터 (title/decision/reason/alternatives/impact case-insensitive). 외부 AI가 영구화된 설계 결정 전체 회수', inputSchema: { type: 'object', properties: { path: { type: 'string' }, query: { type: 'string' } } } },
|
|
8636
8673
|
{ name: 'leerness_plan_list', description: '1.9.119 — plan.md 의 모든 milestone (M-XXXX) 조회 JSON ({ id, title, status, progress, tasks: [{ done, text }] }[]). 외부 AI가 영구화된 계획 + 진행률 + tasks checkbox 전체 회수', inputSchema: { type: 'object', properties: { path: { type: 'string' } } } },
|
|
8637
8674
|
{ name: 'leerness_lesson_drop', description: '1.9.124 — lessons.md 에서 특정 lesson 제거 (target: date YYYY-MM-DD 또는 text substring). 잘못 저장한 lesson 제거. 제거된 블록은 .harness/lessons.archive.md 에 자동 보존 (복구 가능)', inputSchema: { type: 'object', properties: { target: { type: 'string' }, path: { type: 'string' } }, required: ['target'] } },
|
|
8638
8675
|
{ name: 'leerness_decision_drop', description: '1.9.125 — decisions.md 에서 특정 결정 제거 (target: date YYYY-MM-DD 또는 title substring). 제거된 블록은 .harness/decisions.archive.md 에 자동 보존', inputSchema: { type: 'object', properties: { target: { type: 'string' }, path: { type: 'string' } }, required: ['target'] } },
|
|
8639
8676
|
{ name: 'leerness_plan_remove', description: '1.9.126 — plan.md 에서 특정 milestone 블록 (### M-XXXX) 제거 (target: M-XXXX 또는 title substring). 제거된 블록은 .harness/plan.archive.md 에 자동 보존. Memory Surface DELETE 5종 완전 완성', inputSchema: { type: 'object', properties: { target: { type: 'string' }, path: { type: 'string' } }, required: ['target'] } },
|
|
8640
|
-
{ name: 'leerness_memory_archive_list', description: '1.9.127 — DELETE 5종 archive 파일 통합 조회 JSON ({ decisions: [], lessons: [], plan: [], totals: { decisions, lessons, plan, all } }). 외부 AI가 과거에 제거된 항목을 회수/복원 후보로 참조. --surface 필터: decisions|lessons|plan', inputSchema: { type: 'object', properties: { surface: { type: 'string' }, path: { type: 'string' } } } },
|
|
8677
|
+
{ name: 'leerness_memory_archive_list', description: '1.9.127 — DELETE 5종 archive 파일 통합 조회 JSON ({ decisions: [], lessons: [], plan: [], totals: { decisions, lessons, plan, all } }). 외부 AI가 과거에 제거된 항목을 회수/복원 후보로 참조. --surface 필터: decisions|lessons|plan. 1.9.138+ --query 키워드 필터 (target/originalHeader case-insensitive 매칭)', inputSchema: { type: 'object', properties: { surface: { type: 'string' }, query: { type: 'string' }, path: { type: 'string' } } } },
|
|
8641
8678
|
{ name: 'leerness_memory_restore', description: '1.9.128 — archive 의 항목을 active 파일로 복귀 (DELETE→RESTORE cycle). surface: decisions|lessons|plan. target: date YYYY-MM-DD 또는 target substring 매칭. 복원된 블록은 archive 에서 제거됨. 🎉 MCP 40 도구 마일스톤', inputSchema: { type: 'object', properties: { surface: { type: 'string', enum: ['decisions', 'lessons', 'plan'] }, target: { type: 'string' }, path: { type: 'string' } }, required: ['surface', 'target'] } },
|
|
8642
8679
|
{ name: 'leerness_task_list', description: '1.9.134 — progress-tracker.md 전체 task 조회 JSON ({ total, tasks: [{ id, status, request, evidence, nextAction, updated }] }). --status 필터 지원 (planned|in-progress|done 등). 외부 AI가 task 상태 회수', inputSchema: { type: 'object', properties: { path: { type: 'string' }, status: { type: 'string' } } } },
|
|
8643
8680
|
{ name: 'leerness_rule_remove', description: '1.9.135 — rules.md 에서 특정 rule 제거 (id: R-XXXX). 제거된 rule 은 .harness/rules.archive.md 에 자동 보존 (복구 가능). Rule surface CRUD MCP 완성 (add/list/remove)', inputSchema: { type: 'object', properties: { id: { type: 'string' }, path: { type: 'string' } }, required: ['id'] } }
|
|
@@ -8704,13 +8741,13 @@ function mcpServeCmd(root) {
|
|
|
8704
8741
|
case 'leerness_plan_add': cliArgs = ['plan', 'add', String(args.text || ''), '--path', targetPath, ...(args.status ? ['--status', args.status] : []), ...(args.progress ? ['--progress', String(args.progress)] : []), ...(args.nextAction ? ['--next', args.nextAction] : [])]; break;
|
|
8705
8742
|
case 'leerness_lesson_save': cliArgs = ['lesson', 'save', String(args.text || ''), '--path', targetPath, ...(args.tag ? ['--tag', args.tag] : [])]; break;
|
|
8706
8743
|
case 'leerness_memory_status': cliArgs = ['memory', 'status', '--path', targetPath, '--json']; break;
|
|
8707
|
-
case 'leerness_lesson_list': cliArgs = ['lesson', 'list', '--path', targetPath, '--json', ...(args.tag ? ['--tag', args.tag] : [])]; break;
|
|
8708
|
-
case 'leerness_decision_list': cliArgs = ['decision', 'list', '--path', targetPath, '--json']; break;
|
|
8744
|
+
case 'leerness_lesson_list': cliArgs = ['lesson', 'list', '--path', targetPath, '--json', ...(args.tag ? ['--tag', args.tag] : []), ...(args.query ? ['--query', args.query] : [])]; break;
|
|
8745
|
+
case 'leerness_decision_list': cliArgs = ['decision', 'list', '--path', targetPath, '--json', ...(args.query ? ['--query', args.query] : [])]; break;
|
|
8709
8746
|
case 'leerness_plan_list': cliArgs = ['plan', 'list', '--path', targetPath, '--json']; break;
|
|
8710
8747
|
case 'leerness_lesson_drop': cliArgs = ['lesson', 'drop', String(args.target || ''), '--path', targetPath]; break;
|
|
8711
8748
|
case 'leerness_decision_drop': cliArgs = ['decision', 'drop', String(args.target || ''), '--path', targetPath]; break;
|
|
8712
8749
|
case 'leerness_plan_remove': cliArgs = ['plan', 'remove', String(args.target || ''), '--path', targetPath]; break;
|
|
8713
|
-
case 'leerness_memory_archive_list': cliArgs = ['memory', 'archive', 'list', '--path', targetPath, '--json', ...(args.surface ? ['--surface', args.surface] : [])]; break;
|
|
8750
|
+
case 'leerness_memory_archive_list': cliArgs = ['memory', 'archive', 'list', '--path', targetPath, '--json', ...(args.surface ? ['--surface', args.surface] : []), ...(args.query ? ['--query', args.query] : [])]; break;
|
|
8714
8751
|
case 'leerness_memory_restore': cliArgs = ['memory', 'restore', String(args.surface || ''), String(args.target || ''), '--path', targetPath]; break;
|
|
8715
8752
|
case 'leerness_task_list': cliArgs = ['task', 'list', '--path', targetPath, '--json', ...(args.status ? ['--status', args.status] : [])]; break;
|
|
8716
8753
|
case 'leerness_rule_remove': cliArgs = ['rule', 'remove', String(args.id || ''), '--path', targetPath]; break;
|