leerness 1.9.137 → 1.9.138

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,26 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.9.138 — 2026-05-20
4
+
5
+ **`leerness memory archive list --query <keyword>` 필터 추가** — archive 항목 키워드 검색.
6
+
7
+ ### Added — --query 필터
8
+ - `target` 또는 `originalHeader` 에 키워드 case-insensitive 매칭
9
+ - 정규식 특수문자는 자동 escape
10
+ - 텍스트 모드 헤더에 `— query: "..."` 표시
11
+ - JSON 모드 응답에 `query` 필드 추가
12
+ - 매칭 0건 시 안내 메시지
13
+
14
+ ### Updated — MCP leerness_memory_archive_list
15
+ - 신규 인자: `{ query? }` (optional)
16
+ - 외부 AI 가 archive 에서 특정 주제 항목만 회수 가능
17
+
18
+ ### 사용 시나리오
19
+ ```
20
+ leerness memory archive list --query PostgreSQL --json
21
+ # → decisions/lessons/plan 중 PostgreSQL 매칭만 반환
22
+ ```
23
+
3
24
  ## 1.9.137 — 2026-05-20
4
25
 
5
26
  **`.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.138-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-68-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.138 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.138';
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,7 @@ 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 매칭).
366
367
 
367
368
  ---
368
369
 
@@ -1547,6 +1548,9 @@ function memoryArchiveListCmd(root, opts = {}) {
1547
1548
  root = absRoot(root);
1548
1549
  const jsonMode = !!opts.json || has('--json');
1549
1550
  const surfaceFilter = arg('--surface', '');
1551
+ // 1.9.138: --query 키워드 필터 (target / originalHeader 매칭, case-insensitive)
1552
+ const queryFilter = arg('--query', '');
1553
+ const queryRe = queryFilter ? new RegExp(queryFilter.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'), 'i') : null;
1550
1554
  const hd = path.join(root, '.harness');
1551
1555
  const archives = {
1552
1556
  decisions: { path: path.join(hd, 'decisions.archive.md'), entries: [] },
@@ -1556,7 +1560,14 @@ function memoryArchiveListCmd(root, opts = {}) {
1556
1560
  for (const k of Object.keys(archives)) {
1557
1561
  if (surfaceFilter && surfaceFilter !== k) continue;
1558
1562
  const a = archives[k];
1559
- if (exists(a.path)) a.entries = _parseArchiveBlocks(read(a.path));
1563
+ if (exists(a.path)) {
1564
+ let entries = _parseArchiveBlocks(read(a.path));
1565
+ // 1.9.138: --query 필터 적용 (target 또는 originalHeader 매칭)
1566
+ if (queryRe) {
1567
+ entries = entries.filter(e => queryRe.test(e.target || '') || queryRe.test(e.originalHeader || ''));
1568
+ }
1569
+ a.entries = entries;
1570
+ }
1560
1571
  }
1561
1572
  const totals = {
1562
1573
  decisions: archives.decisions.entries.length,
@@ -1572,12 +1583,14 @@ function memoryArchiveListCmd(root, opts = {}) {
1572
1583
  plan: archives.plan.entries,
1573
1584
  totals
1574
1585
  };
1586
+ if (queryFilter) payload.query = queryFilter;
1587
+ if (surfaceFilter) payload.surface = surfaceFilter;
1575
1588
  process.stdout.write(JSON.stringify(payload, null, 2) + '\n');
1576
1589
  return;
1577
1590
  }
1578
- log('# 🗑 Memory Archive List (1.9.127)\n');
1591
+ log('# 🗑 Memory Archive List (1.9.127)' + (queryFilter ? ` — query: "${queryFilter}"` : '') + '\n');
1579
1592
  if (totals.all === 0) {
1580
- log('(archive 파일 없음 — 아직 제거된 항목 없음)');
1593
+ log(queryFilter ? `(매칭 archive entry 없음 — query: "${queryFilter}")` : '(archive 파일 없음 — 아직 제거된 항목 없음)');
1581
1594
  return;
1582
1595
  }
1583
1596
  if ((!surfaceFilter || surfaceFilter === 'decisions') && archives.decisions.entries.length) {
@@ -4321,7 +4334,7 @@ function _banner(opts = {}) {
4321
4334
  lines.push('');
4322
4335
  for (const ln of lines) log(ln);
4323
4336
  if (opts.quickStart) {
4324
- log(C.bold(C.cyan(' ✨ 빠른 시작 (1.9.137+ session-workflow Memory CRUD ref67 라운드 자율 누적)')));
4337
+ log(C.bold(C.cyan(' ✨ 빠른 시작 (1.9.138+ archive list --query 필터68 라운드 자율 누적)')));
4325
4338
  log(' ' + C.green('npx leerness@latest init .') + C.dim(' # 신규 프로젝트 + 외부 AI CLI 설정'));
4326
4339
  log(' ' + C.green('npx leerness handoff .') + C.dim(' # 컨텍스트 + lessons + 매칭 skill + history hit + brainstorm hits + 헤드라인'));
4327
4340
  log(' ' + C.green('npx leerness handoff . --quiet') + C.dim(' # 자동화/CI 모드 (1.9.99) — 자동 회수 라인 비활성'));
@@ -8637,7 +8650,7 @@ function mcpServeCmd(root) {
8637
8650
  { 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
8651
  { 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
8652
  { 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' } } } },
8653
+ { 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
8654
  { 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
8655
  { 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
8656
  { 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'] } }
@@ -8710,7 +8723,7 @@ function mcpServeCmd(root) {
8710
8723
  case 'leerness_lesson_drop': cliArgs = ['lesson', 'drop', String(args.target || ''), '--path', targetPath]; break;
8711
8724
  case 'leerness_decision_drop': cliArgs = ['decision', 'drop', String(args.target || ''), '--path', targetPath]; break;
8712
8725
  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;
8726
+ case 'leerness_memory_archive_list': cliArgs = ['memory', 'archive', 'list', '--path', targetPath, '--json', ...(args.surface ? ['--surface', args.surface] : []), ...(args.query ? ['--query', args.query] : [])]; break;
8714
8727
  case 'leerness_memory_restore': cliArgs = ['memory', 'restore', String(args.surface || ''), String(args.target || ''), '--path', targetPath]; break;
8715
8728
  case 'leerness_task_list': cliArgs = ['task', 'list', '--path', targetPath, '--json', ...(args.status ? ['--status', args.status] : [])]; break;
8716
8729
  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.138",
4
4
  "description": "Leerness: 비파괴 마이그레이션, 자동 버전 감지·업데이트, 계획/진행/핸드오프 자동화, 게으름·시크릿·인코딩 자동 가드, Claude Code 슬래시 통합을 갖춘 한국어 우선 AI 개발 하네스.",
5
5
  "keywords": [
6
6
  "leerness",