leerness 1.9.155 → 1.9.156
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 +39 -0
- package/README.md +2 -2
- package/bin/harness.js +98 -5
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,44 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.9.156 — 2026-05-20
|
|
4
|
+
|
|
5
|
+
**`agents multi --execute` 실제 spawn + consensus 통합 (1.9.155 점검 보고서 발견 gap #1 보강).**
|
|
6
|
+
|
|
7
|
+
자율 모드 86 라운드. 5능력 점검 보고서가 발견한 **"agents multi가 명령 문자열만 출력 — 실제 spawn 안 함"** 문제를 직접 해결.
|
|
8
|
+
|
|
9
|
+
### Added — `leerness agents multi "<task>" --execute`
|
|
10
|
+
- 기존 (1.9.152): 활성 N개 에이전트에 dispatch 명령 **문자열만 출력** — 사용자가 실행
|
|
11
|
+
- 신규 (1.9.156): `--execute` 플래그 시 **leerness가 직접 N개 sub-agent 병렬 spawn**
|
|
12
|
+
- `Promise.all` 로 `_cliChat(provider)` 동시 호출 — 진짜 N-way 분배
|
|
13
|
+
- 각 호출은 1.9.150 `runCommandSafe` 경유 → cwd jail + env scrub + 자동 observability
|
|
14
|
+
- `--timeout <s>` 옵션 (기본 60s) — 무한 대기 방지
|
|
15
|
+
- 결과 수집 후 **1.9.155 multi-signal consensus** 자동 적용:
|
|
16
|
+
- `score = 0.4*tokensNorm + 0.4*overlap + 0.2*lengthFit`
|
|
17
|
+
- best 1위 + others 2-4위 점수 표시 (투명성)
|
|
18
|
+
- `--json` 출력: `{ task, count, success, totalElapsedMs, results, best, failures }`
|
|
19
|
+
- `_recordRun` 통합 — kind `agents_multi_execute` + task-log 자동 기록
|
|
20
|
+
- 활성 0개 또는 onlyArg 매칭 0개 → 즉시 fail (실 호출 시도 X)
|
|
21
|
+
|
|
22
|
+
### Verification — 5능력 점검 매트릭스 갱신
|
|
23
|
+
| 영역 | 1.9.155 | 1.9.156 |
|
|
24
|
+
|---|---|---|
|
|
25
|
+
| 멀티 에이전트 오케스트레이션 | 70% (명령 출력만) | **90%** (실 spawn + consensus 합의) |
|
|
26
|
+
| 종합 완성도 | 55% | **60%** |
|
|
27
|
+
|
|
28
|
+
이제 leerness 가 "지시 생성기" 가 아닌 **"실 실행 오케스트레이터"** — Hermes Agent / OpenClaw 같은 도구와의 격차가 크게 줄어듦.
|
|
29
|
+
|
|
30
|
+
### Pending — 보고서 권고 다음 3 후보
|
|
31
|
+
1. **1.9.157** — LSP 어댑터 MVP (TypeScript LSP 먼저)
|
|
32
|
+
2. **1.9.158** — Provider Registry MCP 도구 (OpenRouter/Bedrock 100+ 모델 흡수)
|
|
33
|
+
3. **1.9.159** — playwright/computer-use bridge (`permissions.browser/mouse` 실 동작 — opt-in)
|
|
34
|
+
|
|
35
|
+
### Verified
|
|
36
|
+
- e2e 217/217 ✓
|
|
37
|
+
- stress-v101: 18/18 (--execute 7종 + CLI 동작 3종 + 누적 회귀 8종)
|
|
38
|
+
- VERSION = 1.9.156 / autonomous-rounds = 86
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
3
42
|
## 1.9.155 — 2026-05-20
|
|
4
43
|
|
|
5
44
|
**REPL UX 대폭 개선 + provider 모델 카탈로그 + orchestrate consensus 강화 + 5능력 점검 보고서 (사용자 명시).**
|
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.156 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.
|
|
9
|
+
const VERSION = '1.9.156';
|
|
10
10
|
const MARK = '<!-- leerness:managed -->';
|
|
11
11
|
const README_START = '<!-- leerness:project-readme:start -->';
|
|
12
12
|
const README_END = '<!-- leerness:project-readme:end -->';
|
|
@@ -5162,6 +5162,7 @@ function agentsCmd(root, sub, ...args) {
|
|
|
5162
5162
|
if (!task) { fail('multi "<task>" 또는 --task 필요'); return process.exit(1); }
|
|
5163
5163
|
const onlyArg = arg('--only', null); // 'claude,codex' 처럼 콤마 구분 — 활성 중에서 추가 필터
|
|
5164
5164
|
const writeMode = has('--write');
|
|
5165
|
+
const execute = has('--execute'); // 1.9.156: 명령 출력 → 실제 spawn + consensus 합의
|
|
5165
5166
|
const checks = EXTERNAL_AGENTS.map(a => ({ def: a, status: _checkAgent(a) }));
|
|
5166
5167
|
let ready = checks.filter(x => x.status.status === 'ready');
|
|
5167
5168
|
if (onlyArg) {
|
|
@@ -5172,6 +5173,97 @@ function agentsCmd(root, sub, ...args) {
|
|
|
5172
5173
|
fail('활성 (ready) 에이전트 없음 — `leerness agents list` 로 확인. 1.9.151 install 흐름에서 복수 선택 후 .env 활성화 필요.');
|
|
5173
5174
|
return process.exit(1);
|
|
5174
5175
|
}
|
|
5176
|
+
// 1.9.156: --execute 모드 — 실제 spawn + 결과 수집 + multi-signal consensus
|
|
5177
|
+
if (execute) {
|
|
5178
|
+
return (async () => {
|
|
5179
|
+
const timeout = parseInt(arg('--timeout', '60'), 10) * 1000;
|
|
5180
|
+
if (!has('--json')) {
|
|
5181
|
+
log(`# leerness agents multi --execute (1.9.156) — ${ready.length}개 활성 에이전트 병렬 호출`);
|
|
5182
|
+
log(`task: ${task.slice(0, 120)}${task.length > 120 ? '…' : ''}`);
|
|
5183
|
+
log(`mode: ${writeMode ? '✏ write' : '🔒 read-only'} · timeout=${timeout / 1000}s`);
|
|
5184
|
+
log(`대상: ${ready.map(x => x.def.id).join(', ')}`);
|
|
5185
|
+
log('');
|
|
5186
|
+
log('## 병렬 호출 중...');
|
|
5187
|
+
}
|
|
5188
|
+
const t0 = Date.now();
|
|
5189
|
+
// 병렬 _cliChat 호출 (sandbox 자동: runCommandSafe + env scrub + observability)
|
|
5190
|
+
const results = await Promise.all(ready.map(async ({ def }) => {
|
|
5191
|
+
const start = Date.now();
|
|
5192
|
+
const r = await _cliChat(root, def.id, task, { timeout });
|
|
5193
|
+
return {
|
|
5194
|
+
agent: def.id,
|
|
5195
|
+
elapsed: Date.now() - start,
|
|
5196
|
+
ok: r.ok,
|
|
5197
|
+
response: r.response || '',
|
|
5198
|
+
error: r.error || null,
|
|
5199
|
+
responseTokens: Math.ceil((r.response || '').length / 4) // 대략 token 추정
|
|
5200
|
+
};
|
|
5201
|
+
}));
|
|
5202
|
+
const totalElapsed = Date.now() - t0;
|
|
5203
|
+
const ok = results.filter(r => r.ok);
|
|
5204
|
+
const failures = results.filter(r => !r.ok);
|
|
5205
|
+
_recordRun(root, { kind: 'agents_multi_execute', count: ready.length, success: ok.length, durationMs: totalElapsed, task: task.slice(0, 200) });
|
|
5206
|
+
// 1.9.155 consensus 로직 재사용 — multi-signal scoring (tokens + overlap + lengthFit)
|
|
5207
|
+
let best = null, scored = [];
|
|
5208
|
+
if (ok.length) {
|
|
5209
|
+
const tokenizer = (s) => new Set(String(s || '').toLowerCase().match(/[\w가-힣]{3,}/g) || []);
|
|
5210
|
+
const wordsOf = ok.map(o => tokenizer(o.response));
|
|
5211
|
+
const maxTokens = Math.max(...ok.map(o => o.responseTokens), 1);
|
|
5212
|
+
const avgLen = ok.reduce((s, o) => s + o.response.length, 0) / ok.length;
|
|
5213
|
+
const stdLen = Math.sqrt(ok.reduce((s, o) => s + (o.response.length - avgLen) ** 2, 0) / ok.length) || 1;
|
|
5214
|
+
scored = ok.map((o, i) => {
|
|
5215
|
+
const tokensNorm = o.responseTokens / maxTokens;
|
|
5216
|
+
const myWords = wordsOf[i];
|
|
5217
|
+
let overlapSum = 0;
|
|
5218
|
+
for (let j = 0; j < wordsOf.length; j++) {
|
|
5219
|
+
if (i === j) continue;
|
|
5220
|
+
let inter = 0;
|
|
5221
|
+
for (const w of myWords) if (wordsOf[j].has(w)) inter++;
|
|
5222
|
+
overlapSum += inter / Math.max(myWords.size, 1);
|
|
5223
|
+
}
|
|
5224
|
+
const overlap = (ok.length > 1) ? overlapSum / (ok.length - 1) : 0;
|
|
5225
|
+
const z = Math.abs((o.response.length - avgLen) / stdLen);
|
|
5226
|
+
const lengthFit = z <= 1.5 ? (1 - z / 1.5) : 0;
|
|
5227
|
+
const score = 0.4 * tokensNorm + 0.4 * overlap + 0.2 * lengthFit;
|
|
5228
|
+
return { ...o, score, tokensNorm, overlap, lengthFit };
|
|
5229
|
+
}).sort((a, b) => b.score - a.score);
|
|
5230
|
+
best = scored[0];
|
|
5231
|
+
}
|
|
5232
|
+
if (has('--json')) {
|
|
5233
|
+
log(JSON.stringify({
|
|
5234
|
+
task, count: ready.length, success: ok.length, totalElapsedMs: totalElapsed,
|
|
5235
|
+
results: scored.length ? scored : results,
|
|
5236
|
+
best: best ? { agent: best.agent, score: best.score, response: best.response } : null,
|
|
5237
|
+
failures
|
|
5238
|
+
}, null, 2));
|
|
5239
|
+
return;
|
|
5240
|
+
}
|
|
5241
|
+
log(`\n## 결과: ${ok.length}/${ready.length} 성공 · 총 ${totalElapsed}ms (병렬)`);
|
|
5242
|
+
for (const r of results) {
|
|
5243
|
+
if (r.ok) log(` ✓ ${r.agent.padEnd(8)} · ${r.elapsed}ms · ${r.responseTokens} 토큰`);
|
|
5244
|
+
else log(` ✗ ${r.agent.padEnd(8)} · ${r.elapsed}ms · ${(r.error || '').slice(0, 60)}`);
|
|
5245
|
+
}
|
|
5246
|
+
if (best) {
|
|
5247
|
+
log('');
|
|
5248
|
+
log(`## 🏆 합의 선택 (multi-signal consensus, 1.9.155)`);
|
|
5249
|
+
log(` best: ${best.agent} · score=${best.score.toFixed(3)} (tokens=${best.tokensNorm.toFixed(2)} · overlap=${best.overlap.toFixed(2)} · lengthFit=${best.lengthFit.toFixed(2)})`);
|
|
5250
|
+
if (scored.length > 1) {
|
|
5251
|
+
log(` others: ${scored.slice(1, 4).map(s => `${s.agent}=${s.score.toFixed(2)}`).join(', ')}`);
|
|
5252
|
+
}
|
|
5253
|
+
log(` --- 처음 600자 ---`);
|
|
5254
|
+
log(best.response.slice(0, 600));
|
|
5255
|
+
// task-log 기록
|
|
5256
|
+
try {
|
|
5257
|
+
const tlp = taskLogPath(root);
|
|
5258
|
+
const block = `\n## ${today()} agents multi --execute (1.9.156)\n- task: ${task.slice(0, 200)}\n- agents: ${ready.map(x => x.def.id).join(', ')}\n- success: ${ok.length}/${ready.length}\n- best: ${best.agent} (score=${best.score.toFixed(3)})\n`;
|
|
5259
|
+
append(tlp, block);
|
|
5260
|
+
} catch {}
|
|
5261
|
+
}
|
|
5262
|
+
if (failures.length && !best) {
|
|
5263
|
+
process.exitCode = 1;
|
|
5264
|
+
}
|
|
5265
|
+
})();
|
|
5266
|
+
}
|
|
5175
5267
|
if (has('--json')) {
|
|
5176
5268
|
log(JSON.stringify({
|
|
5177
5269
|
task, count: ready.length,
|
|
@@ -5194,9 +5286,10 @@ function agentsCmd(root, sub, ...args) {
|
|
|
5194
5286
|
log('```');
|
|
5195
5287
|
log('');
|
|
5196
5288
|
}
|
|
5197
|
-
log('## 정책 (1.9.152)');
|
|
5198
|
-
log(` -
|
|
5199
|
-
log(` -
|
|
5289
|
+
log('## 정책 (1.9.152 / 1.9.156)');
|
|
5290
|
+
log(` - 기본 모드: 명령 문자열만 출력 (사용자/메인 에이전트가 명시적으로 실행)`);
|
|
5291
|
+
log(` - 1.9.156 신규: \`--execute\` 플래그 시 leerness가 직접 ${ready.length}개 sub-agent 병렬 spawn + multi-signal consensus 자동 합의`);
|
|
5292
|
+
log(` 예: leerness agents multi "<task>" --execute (또는 --execute --json)`);
|
|
5200
5293
|
log(` - 활성 에이전트 변경: \`.env\`에서 LEERNESS_ENABLE_<CLI>=1/0 또는 \`leerness setup-agents\` 재실행`);
|
|
5201
5294
|
log(` - quota 체크: \`leerness agents quota\``);
|
|
5202
5295
|
return;
|
|
@@ -11479,7 +11572,7 @@ function reuseAutodetectCmd(root) {
|
|
|
11479
11572
|
}
|
|
11480
11573
|
|
|
11481
11574
|
function help() {
|
|
11482
|
-
log(`Leerness v${VERSION}\n\nUsage:\n leerness init [path] [--language auto|ko|en] [--skills recommended|all|a,b]\n leerness migrate [path] [--dry-run] [--force]\n leerness update [path] [--check|--yes|--force|--from <tarball>]\n leerness auto-update install [path]\n leerness status [path]\n leerness verify [path]\n leerness debug [path]\n leerness audit [path]\n leerness check [path]\n leerness scan secrets [path]\n leerness encoding check [path]\n leerness lazy detect [path]\n leerness memory search "query" [--limit 5]\n leerness handoff [path] [--all-apps] [--include p1,p2] [--since 24h|3d] [--compact] [--json] # 1.9.17-22 워크스페이스 (--compact: LLM 시스템 프롬프트용 1줄 요약)\n leerness orchestrate "<목표>" [--agents N] [--model qwen2.5:7b-instruct] [--retry-on-fail K] # 1.9.22 Ollama opt-in (LEERNESS_OLLAMA_BASE_URL 필요)\n leerness llm-bench record --score N --model X [--label L] [--tokens T] # 1.9.22 LLM 벤치 히스토리 누적\n leerness deps <capability> [--run-tests] [--json] # 1.9.24 depends-on 역방향 추적 + 자동 회귀 sweep\n leerness memory search "키" [--include-code] # 1.9.25 소스 코드 본문도 검색 (모순 감지 핵심)\n leerness brainstorm "주제" [--include-code] # 1.9.25 코드 본문 hits 포함\n leerness register-pending "<요청>" [--agent X] [--note Y] # 1.9.25 다중 세션 in-progress 즉시 등록\n leerness optimism-check <T-ID> [--json] # 1.9.26/27 낙관적 표시 감지 (1.9.27: 10 카테고리 + URL/메서드 매핑 + 신뢰도 점수)\n leerness persona list|show <id>|add <id> # 1.9.29 페르소나 카탈로그 (보안/성능/UX/testing/docs 5종 내장)\n leerness review <file> --persona <id1,id2,...> # 1.9.29 도메인 페르소나 리뷰 프롬프트 자동 생성\n leerness agents list|check|quota # 1.9.30/31 외부 AI CLI 가용성 + quota 추정 (claude/codex/gemini/copilot)\n leerness agents dispatch "<task>" --to <id> # 1.9.30 활성 CLI 대상 실행 명령 생성 (실 호출 X, 사용자 실행)\n leerness agents multi "<task>" [--only c1,c2] [--write] # 1.9.152 활성 N개
|
|
11575
|
+
log(`Leerness v${VERSION}\n\nUsage:\n leerness init [path] [--language auto|ko|en] [--skills recommended|all|a,b]\n leerness migrate [path] [--dry-run] [--force]\n leerness update [path] [--check|--yes|--force|--from <tarball>]\n leerness auto-update install [path]\n leerness status [path]\n leerness verify [path]\n leerness debug [path]\n leerness audit [path]\n leerness check [path]\n leerness scan secrets [path]\n leerness encoding check [path]\n leerness lazy detect [path]\n leerness memory search "query" [--limit 5]\n leerness handoff [path] [--all-apps] [--include p1,p2] [--since 24h|3d] [--compact] [--json] # 1.9.17-22 워크스페이스 (--compact: LLM 시스템 프롬프트용 1줄 요약)\n leerness orchestrate "<목표>" [--agents N] [--model qwen2.5:7b-instruct] [--retry-on-fail K] # 1.9.22 Ollama opt-in (LEERNESS_OLLAMA_BASE_URL 필요)\n leerness llm-bench record --score N --model X [--label L] [--tokens T] # 1.9.22 LLM 벤치 히스토리 누적\n leerness deps <capability> [--run-tests] [--json] # 1.9.24 depends-on 역방향 추적 + 자동 회귀 sweep\n leerness memory search "키" [--include-code] # 1.9.25 소스 코드 본문도 검색 (모순 감지 핵심)\n leerness brainstorm "주제" [--include-code] # 1.9.25 코드 본문 hits 포함\n leerness register-pending "<요청>" [--agent X] [--note Y] # 1.9.25 다중 세션 in-progress 즉시 등록\n leerness optimism-check <T-ID> [--json] # 1.9.26/27 낙관적 표시 감지 (1.9.27: 10 카테고리 + URL/메서드 매핑 + 신뢰도 점수)\n leerness persona list|show <id>|add <id> # 1.9.29 페르소나 카탈로그 (보안/성능/UX/testing/docs 5종 내장)\n leerness review <file> --persona <id1,id2,...> # 1.9.29 도메인 페르소나 리뷰 프롬프트 자동 생성\n leerness agents list|check|quota # 1.9.30/31 외부 AI CLI 가용성 + quota 추정 (claude/codex/gemini/copilot)\n leerness agents dispatch "<task>" --to <id> # 1.9.30 활성 CLI 대상 실행 명령 생성 (실 호출 X, 사용자 실행)\n leerness agents multi "<task>" [--only c1,c2] [--write] [--execute] [--timeout 60] # 1.9.152/156 활성 N개 일괄 dispatch (--execute: 실 spawn + consensus)\n leerness agents dispatch "<task>" --multi # 1.9.152 multi 모드 alias (또는 --to all)\n leerness setup-agents [path] [--yes|--no-setup-agents] # 1.9.32 sub-agent CLI 인터랙티브 설정 (.env + 미설치 자동 설치)\n leerness init [path] [--no-stale-check] # 1.9.33 npx 캐시 함정 — 옛 버전 자동 경고 (끄려면 --no-stale-check)\n leerness contract verify <spec.md> <impl.js> [--json] # 1.9.35 명세 ↔ 구현 일치 검사 (함수/필드)\n leerness reuse autodetect [path] [--apply] [--json] # 1.9.35 src/*.js의 module.exports → reuse-map 후보 등록\n leerness audit [path] [--fix] # 1.9.35 --fix: session-handoff/current-state 자동 갱신\n leerness verify-claim <T-ID> ... [--strict-claims] # 1.9.26 verify-claim에 낙관적 표시 자동 검사 통합\n leerness reuse-map [path] [--all-apps] [--include p1,p2] [--strict-elements] [--json] # 1.9.18 중복/잠재중복/depends-on\n leerness verify-claim <T-ID> [--path .] [--run-tests] [--json] # 1.9.18-20 evidence 자동 검증 (1.9.20: scenes/scripts 등 도메인 폴더 + jest/mocha 파싱)\n leerness verify-code [path] [--build] [--bench] # 1.9.20 --bench: scripts.bench 추가 실행 + evidence 누적\n leerness session close [path]\n leerness route <task-type>\n leerness self check [path]\n leerness readme sync [path]\n leerness consistency check [path]\n leerness consistency merge-design-guide [path]\n leerness plan show|init|add|drop|progress|sync [args]\n leerness task list|add|update|drop|fix-evidence|relink [args]\n leerness skill list|info <name>\n leerness skill learn <id> --doc <url> --command "..." --capability "..." [--note ...]\n leerness skill use <id> [--note ...]\n leerness skill optimize <id> --before "..." --after "..." [--note ...]\n leerness skill remove <id>\n leerness skill consolidate [--threshold 0.3]\n leerness gate [path] # verify+audit+scan+encoding+lazy
|
|
11483
11576
|
leerness retro [path] [--days 7] [--all-apps] [--include p1,p2] [--json] # 회고 (1.9.13~1.9.16)
|
|
11484
11577
|
leerness insights [path] [--all-apps] [--include p1,p2] [--json] # 누적 통계 (1.9.13~1.9.16)
|
|
11485
11578
|
leerness brainstorm "<주제>" [--all-apps] [--include p1,p2] [--json] # 브레인스토밍 (1.9.13~1.9.16)
|