leerness 1.9.161 → 1.9.163

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,84 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.9.163 — 2026-05-20
4
+
5
+ **`leerness health` 에 5능력 매트릭스 자동 평가 통합.**
6
+
7
+ 자율 모드 93 라운드. 1.9.155 sub-agent 점검 (수동) → **코드 기반 자동 평가**로 진화. 사용자가 매 health 호출 시 leerness 자기 평가 즉시 확인.
8
+
9
+ ### Added — `health` 출력 + `health --json` 의 `capabilityMatrix` 필드
10
+ 5능력 자동 측정 (코드 grep 기반):
11
+
12
+ | 능력 | 측정 방법 | 현재 점수 |
13
+ |---|---|---|
14
+ | (1) 웹 자동화 | playwright/puppeteer/chromium import 검출 | **5%** (실 코드 미구현) |
15
+ | (2) PC 조작 | robotjs/nut-tree import 검출 | **5%** (필드만 있음) |
16
+ | (3) 멀티 에이전트 오케스트레이션 | `--execute` + `multi-signal consensus` 코드 | **90%** (1.9.156+1.9.155) |
17
+ | (4) REPL multi-provider | `_agentRepl` + `_cliChat` 검출 | **90%** (5종 provider) |
18
+ | (5) MCP 도구 | `leerness_*` count ≥ 50 | **100%** (51 도구) |
19
+
20
+ **종합 58% (beta-ready)** — 사용자가 leerness 의 현재 위치를 단일 명령으로 확인.
21
+
22
+ ### Assessment 라벨
23
+ - `production-ready` — 종합 ≥ 70%
24
+ - `beta-ready` — 종합 ≥ 50%
25
+ - `mvp` — 종합 < 50%
26
+
27
+ ### Use Cases
28
+ - 사용자가 `leerness health` 한 번으로 5능력 현황 즉시 파악
29
+ - 외부 AI 가 `leerness_health` MCP 호출 시 `capabilityMatrix.summary` 받음 (자기-점검)
30
+ - 다음 라운드 우선순위 결정 — 가장 낮은 점수 능력부터 보강 (현재: 웹 자동화 / PC 조작)
31
+ - 1.9.155 sub-agent 점검 (110초 소요) → 1.9.163 자동 (수십 ms) — 4000x 빠름
32
+
33
+ ### Headline 진화 (1.9.162) + Health 진화 (1.9.163) 시너지
34
+ - 매 세션: handoff 헤드라인 `🪄 slash 24h` 로 활용도 확인
35
+ - 정기 점검: `leerness health` 로 5능력 매트릭스 자동 평가
36
+ - 사용자 결정: 점수가 낮은 영역 → 다음 라운드 후보 자동 도출
37
+
38
+ ### Verified
39
+ - e2e 217/217 ✓
40
+ - stress-v108: 14/14 (capabilityMatrix 7종 + 누적 회귀 7종)
41
+ - VERSION = 1.9.163 / autonomous-rounds = 93
42
+
43
+ ---
44
+
45
+ ## 1.9.162 — 2026-05-20
46
+
47
+ **handoff 헤드라인 9번째 요소 — REPL slash 사용량 (24h) 노출.**
48
+
49
+ 자율 모드 92 라운드. 1.9.149 observability `runs/*.jsonl` 의 실용화 — REPL 활용도 가시화.
50
+
51
+ ### Added — 헤드라인 `🪄 slash 24h N회`
52
+ - 1.9.150/161 REPL slash 명령 8종 (`:verify` `:audit` `:handoff` `:health` `:lessons` `:brainstorm` `:tasks` `:plan`) 호출 빈도
53
+ - `.harness/runs/*.jsonl` 에서 `kind: 'agent_repl_slash'` + 24h 이내 entry 카운트
54
+ - 최근 200 파일만 스캔 (성능 보호)
55
+ - 슬래시 호출 없으면 노출 안 함 (노이즈 최소화)
56
+
57
+ ### Headline 진화
58
+ | 요소 | 도입 |
59
+ |---|---|
60
+ | drift level | 1.9.81 |
61
+ | 🔒 보안 | 1.9.81 |
62
+ | 🔌 MCP N회 | 1.9.81 |
63
+ | 📒 skill query | 1.9.81 |
64
+ | 📚 N skills | 1.9.81 |
65
+ | ⚕ health | 1.9.93 |
66
+ | 🧠 mem T/D/R/P/L | 1.9.113 |
67
+ | 🤖 agents N | 1.9.152 |
68
+ | **🪄 slash 24h** | **1.9.162** |
69
+
70
+ ### Use Cases
71
+ - 메인 에이전트가 매 세션 시작 시 "어제 REPL을 N회 사용했군 → 메모리 누적 신호" 즉시 인지
72
+ - 사용자가 leerness 도입 효과 추이 가시화
73
+ - observability lite (1.9.149) 의 첫 실용 application
74
+
75
+ ### Verified
76
+ - e2e 217/217 ✓
77
+ - stress-v107: 13/13 (헤드라인 9번째 6종 + 누적 회귀 7종)
78
+ - VERSION = 1.9.162 / autonomous-rounds = 92
79
+
80
+ ---
81
+
3
82
  ## 1.9.161 — 2026-05-20
4
83
 
5
84
  **REPL Memory Slash 4종 추가 — Memory Surface 즉시 조회 (1.9.150 slash 패턴 확장).**
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.161-green)]() [![tests](https://img.shields.io/badge/e2e-217%2F217-success)]() [![stress](https://img.shields.io/badge/stress--v106-13%2F13-success)]() [![mcp](https://img.shields.io/badge/MCP--tools-50-brightgreen)]() [![rounds](https://img.shields.io/badge/autonomous--rounds-91-blueviolet)]() [![main-push](https://img.shields.io/badge/release--main--push-22_rounds-success)]() [![repl-slash](https://img.shields.io/badge/REPL_slash-8_commands-success)]() [![provider-crud](https://img.shields.io/badge/provider_registry-CRUD%2Bsync-success)]() [![sandbox](https://img.shields.io/badge/runCommandSafe-cwd_jail%2Benv_scrub-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.163-green)]() [![tests](https://img.shields.io/badge/e2e-217%2F217-success)]() [![stress](https://img.shields.io/badge/stress--v108-14%2F14-success)]() [![mcp](https://img.shields.io/badge/MCP--tools-50-brightgreen)]() [![rounds](https://img.shields.io/badge/autonomous--rounds-93-blueviolet)]() [![main-push](https://img.shields.io/badge/release--main--push-24_rounds-success)]() [![capability](https://img.shields.io/badge/5_capability_matrix-58%25_beta--ready-yellow)]() [![provider-crud](https://img.shields.io/badge/provider_registry-CRUD%2Bsync-success)]() [![sandbox](https://img.shields.io/badge/runCommandSafe-cwd_jail%2Benv_scrub-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.161 AI Agent Reliability Harness + Sandbox ║
15
+ ║ v1.9.163 AI Agent Reliability Harness + Sandbox ║
16
16
  ║ verify · remember · orchestrate · audit · sandbox · 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.161';
9
+ const VERSION = '1.9.163';
10
10
  const MARK = '<!-- leerness:managed -->';
11
11
  const README_START = '<!-- leerness:project-readme:start -->';
12
12
  const README_END = '<!-- leerness:project-readme:end -->';
@@ -2965,10 +2965,30 @@ function handoff(root) {
2965
2965
  parts.push(`🤖 agents ${ready.length} (${ready.map(c => c.id).join(',')})`);
2966
2966
  }
2967
2967
  } catch {}
2968
+ // 9) 1.9.162: REPL slash 사용량 (24h) — 1.9.149 observability runs/*.jsonl 활용
2969
+ // REPL slash 명령 (1.9.150 + 1.9.161 = 8종) 사용 빈도 노출 → 사용자가 REPL 활용도 인지
2970
+ try {
2971
+ const runsDir = _runsDir(root);
2972
+ if (exists(runsDir)) {
2973
+ const cutoff = Date.now() - 24 * 3600 * 1000;
2974
+ const files = fs.readdirSync(runsDir).filter(f => f.endsWith('.jsonl'));
2975
+ let slashCount = 0;
2976
+ for (const f of files.slice(-200)) { // 최근 200 파일만 (성능)
2977
+ try {
2978
+ const txt = read(path.join(runsDir, f));
2979
+ for (const line of txt.split('\n').filter(Boolean)) {
2980
+ const j = JSON.parse(line);
2981
+ if (j.kind === 'agent_repl_slash' && j.at && new Date(j.at).getTime() >= cutoff) slashCount++;
2982
+ }
2983
+ } catch {}
2984
+ }
2985
+ if (slashCount > 0) parts.push(`🪄 slash 24h ${slashCount}회`);
2986
+ }
2987
+ } catch {}
2968
2988
  if (parts.length) {
2969
2989
  const isTty = process.stdout && process.stdout.isTTY;
2970
2990
  const cy = s => isTty ? `\x1b[36m${s}\x1b[0m` : s;
2971
- log(cy(`📊 헤드라인 (1.9.81/93/113/152): ${parts.join(' · ')}`));
2991
+ log(cy(`📊 헤드라인 (1.9.81/93/113/152/162): ${parts.join(' · ')}`));
2972
2992
  }
2973
2993
  } catch {}
2974
2994
  }
@@ -11512,6 +11532,45 @@ function healthCmd(root) {
11512
11532
  summary: `F${fNodesHe.length}/E${edgeCount}${isolated > 0 ? `/iso${isolated}` : ''}`
11513
11533
  };
11514
11534
  } catch { out.featureGraph = { error: 'featureGraph 점검 실패' }; }
11535
+ // 1.9.163: 5능력 매트릭스 자동 평가 (1.9.155 sub-agent 점검 → 코드 기반 자동화)
11536
+ // 각 능력을 코드 grep 으로 검출 → 0~100 점수. 사용자가 매 health 호출 시 leerness 자기 평가 확인.
11537
+ try {
11538
+ const harnessSrc = read(__filename);
11539
+ const cap = {};
11540
+ // (1) 웹 자동화 — playwright/puppeteer/chromium import 존재?
11541
+ cap.webAutomation = /require\(['"]playwright['"]\)|require\(['"]puppeteer['"]\)|require\(['"]chromium['"]\)/.test(harnessSrc)
11542
+ ? { score: 90, status: '✓', evidence: 'playwright/puppeteer import 검출' }
11543
+ : { score: 5, status: '❌', evidence: 'permissions.browser=toggle만 (실 코드 미구현)' };
11544
+ // (2) PC 조작 — robotjs/nut-js/iohook/xdotool import?
11545
+ cap.pcAutomation = /require\(['"]robotjs['"]\)|require\(['"]@nut-tree/.test(harnessSrc)
11546
+ ? { score: 90, status: '✓', evidence: 'robotjs/nut-tree import 검출' }
11547
+ : { score: 5, status: '❌', evidence: 'permissions.mouse/keyboard=필드만 (실 사용처 0)' };
11548
+ // (3) 멀티 에이전트 오케스트레이션 — agents multi --execute + consensus 로직?
11549
+ const hasExecute = /const execute = has\('--execute'\)/.test(harnessSrc);
11550
+ const hasConsensus = /multi-signal consensus/.test(harnessSrc);
11551
+ cap.multiAgentOrchestration = (hasExecute && hasConsensus)
11552
+ ? { score: 90, status: '✓', evidence: '실 spawn + multi-signal consensus (1.9.156+1.9.155)' }
11553
+ : { score: 50, status: '⚠', evidence: '명령 출력만 (1.9.152 기본 모드)' };
11554
+ // (4) REPL multi-provider — _agentRepl + _cliChat 5종?
11555
+ const hasRepl = /async function _agentRepl/.test(harnessSrc);
11556
+ const hasCliChat = /async function _cliChat/.test(harnessSrc);
11557
+ cap.replMultiProvider = (hasRepl && hasCliChat)
11558
+ ? { score: 90, status: '✓', evidence: 'ollama/claude/codex/gemini/copilot 5종 (1.9.149+1.9.153)' }
11559
+ : { score: 30, status: '⚠', evidence: 'REPL 미완성' };
11560
+ // (5) MCP 도구 — tools array 카운트
11561
+ const toolsMatch = harnessSrc.match(/{ name: 'leerness_/g);
11562
+ const toolCount = toolsMatch ? toolsMatch.length : 0;
11563
+ cap.mcpTools = toolCount >= 50
11564
+ ? { score: 100, status: '✓', evidence: `${toolCount}/50+ 도구 (1.9.159 CRUD 완성)` }
11565
+ : { score: Math.round((toolCount / 50) * 100), status: toolCount > 30 ? '✓' : '⚠', evidence: `${toolCount} 도구` };
11566
+ const avgScore = Math.round((cap.webAutomation.score + cap.pcAutomation.score + cap.multiAgentOrchestration.score + cap.replMultiProvider.score + cap.mcpTools.score) / 5);
11567
+ out.capabilityMatrix = {
11568
+ capabilities: cap,
11569
+ overallScore: avgScore,
11570
+ summary: `웹${cap.webAutomation.score}/PC${cap.pcAutomation.score}/멀티${cap.multiAgentOrchestration.score}/REPL${cap.replMultiProvider.score}/MCP${cap.mcpTools.score} · 종합 ${avgScore}%`,
11571
+ assessment: avgScore >= 70 ? 'production-ready' : avgScore >= 50 ? 'beta-ready' : 'mvp'
11572
+ };
11573
+ } catch { out.capabilityMatrix = { error: '5능력 매트릭스 평가 실패' }; }
11515
11574
  // 6) issues 요약 (사용자 글로벌 룰 가시화)
11516
11575
  const issues = [];
11517
11576
  if (out.checks.drift?.level && !/healthy/.test(out.checks.drift.level)) issues.push(`drift ${out.checks.drift.level}`);
@@ -11552,6 +11611,18 @@ function healthCmd(root) {
11552
11611
  log(`## tasks`);
11553
11612
  const tb = out.checks.tasks?.byStatus || {};
11554
11613
  log(` 총 ${out.checks.tasks?.total || 0}건: ${Object.entries(tb).map(([s, n]) => `${s}=${n}`).join(', ') || '없음'}`);
11614
+ // 1.9.163: 5능력 매트릭스 — 1.9.155 sub-agent 점검의 코드 기반 자동 평가
11615
+ if (out.capabilityMatrix && !out.capabilityMatrix.error) {
11616
+ log('');
11617
+ log(`## 🧪 5능력 매트릭스 (1.9.163 자동 평가)`);
11618
+ const cm = out.capabilityMatrix;
11619
+ log(` 종합: ${cm.overallScore}% (${cm.assessment})`);
11620
+ log(` (1) 웹 자동화 ${cm.capabilities.webAutomation.status} ${cm.capabilities.webAutomation.score}% · ${cm.capabilities.webAutomation.evidence}`);
11621
+ log(` (2) PC 조작 ${cm.capabilities.pcAutomation.status} ${cm.capabilities.pcAutomation.score}% · ${cm.capabilities.pcAutomation.evidence}`);
11622
+ log(` (3) 멀티 오케스트레이션 ${cm.capabilities.multiAgentOrchestration.status} ${cm.capabilities.multiAgentOrchestration.score}% · ${cm.capabilities.multiAgentOrchestration.evidence}`);
11623
+ log(` (4) REPL multi-provider ${cm.capabilities.replMultiProvider.status} ${cm.capabilities.replMultiProvider.score}% · ${cm.capabilities.replMultiProvider.evidence}`);
11624
+ log(` (5) MCP 도구 ${cm.capabilities.mcpTools.status} ${cm.capabilities.mcpTools.score}% · ${cm.capabilities.mcpTools.evidence}`);
11625
+ }
11555
11626
  if (issues.length) {
11556
11627
  log('');
11557
11628
  log(`## ⚠ Issues (${issues.length})`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "leerness",
3
- "version": "1.9.161",
3
+ "version": "1.9.163",
4
4
  "description": "Leerness: 비파괴 마이그레이션, 자동 버전 감지·업데이트, 계획/진행/핸드오프 자동화, 게으름·시크릿·인코딩 자동 가드, Claude Code 슬래시 통합을 갖춘 한국어 우선 AI 개발 하네스.",
5
5
  "keywords": [
6
6
  "leerness",