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 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
- [![npm](https://img.shields.io/badge/npm-leerness-blue)](https://www.npmjs.com/package/leerness) [![version](https://img.shields.io/badge/version-1.9.137-green)]() [![tests](https://img.shields.io/badge/e2e-219%2F219-success)]() [![mcp](https://img.shields.io/badge/MCP--tools-42-blue)]() [![json](https://img.shields.io/badge/--json-20_commands-blueviolet)]() [![rounds](https://img.shields.io/badge/autonomous--rounds-67-blueviolet)]() [![mcp-crud](https://img.shields.io/badge/MCP--CRUD--5surfaces-complete-success)]() [![license](https://img.shields.io/badge/license-MIT-lightgrey)]()
5
+ [![npm](https://img.shields.io/badge/npm-leerness-blue)](https://www.npmjs.com/package/leerness) [![version](https://img.shields.io/badge/version-1.9.139-green)]() [![tests](https://img.shields.io/badge/e2e-219%2F219-success)]() [![mcp](https://img.shields.io/badge/MCP--tools-42-blue)]() [![json](https://img.shields.io/badge/--json-20_commands-blueviolet)]() [![rounds](https://img.shields.io/badge/autonomous--rounds-69-blueviolet)]() [![mcp-crud](https://img.shields.io/badge/MCP--CRUD--5surfaces-complete-success)]() [![license](https://img.shields.io/badge/license-MIT-lightgrey)]()
6
6
 
7
7
  ```
8
8
  ╔══════════════════════════════════════════════════════════════╗
@@ -12,7 +12,7 @@
12
12
  ║ ██║ ██╔══╝ ██╔══╝ ██╔══██╗██║╚██╗██║██╔══╝ ╚════██║ ║
13
13
  ║ ███████╗███████╗███████╗██║ ██║██║ ╚████║███████╗███████║ ║
14
14
  ║ ╚══════╝╚══════╝╚══════╝╚═╝ ╚═╝╚═╝ ╚═══╝╚══════╝╚══════╝ ║
15
- ║ v1.9.137 AI Agent Reliability Harness ║
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.137';
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)) a.entries = _parseArchiveBlocks(read(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
- process.stdout.write(JSON.stringify({ version: VERSION, root, total: 0, lessons: [], tag: tagFilter }, null, 2) + '\n');
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
- process.stdout.write(JSON.stringify({ version: VERSION, root, total: lessons.length, lessons, tag: tagFilter }, null, 2) + '\n');
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 (tagFilter) ok(`"${tagFilter}" 태그 lesson 없음`);
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
- process.stdout.write(JSON.stringify({ version: VERSION, root, total: 0, decisions: [] }, null, 2) + '\n');
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
- decisions.push({
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
- process.stdout.write(JSON.stringify({ version: VERSION, root, total: decisions.length, decisions }, null, 2) + '\n');
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.137+ session-workflow Memory CRUD ref67 라운드 자율 누적)')));
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가 영구화된 설계 결정 전체 회수 (Decision + Reason/Alternatives/Impact 메타데이터 포함)', inputSchema: { type: 'object', properties: { path: { type: 'string' } } } },
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;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "leerness",
3
- "version": "1.9.137",
3
+ "version": "1.9.139",
4
4
  "description": "Leerness: 비파괴 마이그레이션, 자동 버전 감지·업데이트, 계획/진행/핸드오프 자동화, 게으름·시크릿·인코딩 자동 가드, Claude Code 슬래시 통합을 갖춘 한국어 우선 AI 개발 하네스.",
5
5
  "keywords": [
6
6
  "leerness",