leerness 1.9.75 → 1.9.77
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 +48 -0
- package/README.md +4 -2
- package/bin/harness.js +40 -4
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,53 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.9.77 — 2026-05-20
|
|
4
|
+
|
|
5
|
+
**MCP server 15번째 도구 `leerness_brainstorm` 추가** (1.9.72 brainstorm 외부 노출).
|
|
6
|
+
|
|
7
|
+
### Added — MCP 15번째 도구
|
|
8
|
+
- `leerness_brainstorm` — 1.9.16/72 brainstorm 명령을 MCP 도구로 노출.
|
|
9
|
+
- inputSchema: `{ topic: string (required), path: string, allApps: boolean }`
|
|
10
|
+
- 응답: brainstorm --json 결과 (decisions + skills + tasks + rules + evidence + lessons + skillHistory + taskLogFails).
|
|
11
|
+
- 외부 AI 에이전트가 새 작업 시작 전 누적 컨텍스트 자동 회수 가능.
|
|
12
|
+
- MCP server 도구 카운트: **14 → 15**.
|
|
13
|
+
|
|
14
|
+
### Use Case
|
|
15
|
+
- Claude Code / Cursor 가 사용자 요청을 받으면 자동으로 `brainstorm` 호출 → 같은 주제 과거 결정/스킬/실패 회수.
|
|
16
|
+
- 같은 실수 반복 방지 + 누적 학습 활용.
|
|
17
|
+
|
|
18
|
+
### Verified
|
|
19
|
+
- stress-v23 — MCP 15 도구 + brainstorm 호출 + 1.9.43~76 누적 회귀 + 성능.
|
|
20
|
+
- e2e 회귀: 219/219 PASS 유지.
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## 1.9.76 — 2026-05-20
|
|
25
|
+
|
|
26
|
+
**`leerness handoff`에 보안 상태 요약 자동 표시** (1.9.71 env + 1.9.75 gitignore 결합).
|
|
27
|
+
|
|
28
|
+
### Added — handoff 보안 요약
|
|
29
|
+
- 매 `leerness handoff` 시 `.env` 파일이 존재하면 다음을 자동 검증해 1-2 line으로 표시:
|
|
30
|
+
- `.env→.env.example` 누락 키 (1.9.71)
|
|
31
|
+
- `.gitignore` 시크릿 패턴 누락 (1.9.75)
|
|
32
|
+
- 정상 시 출력 없음 (잡음 방지).
|
|
33
|
+
- 위험 시:
|
|
34
|
+
```
|
|
35
|
+
## 🔒 보안 요약 (1.9.76) — N건 주의
|
|
36
|
+
⚠ .env→.env.example 누락 X건
|
|
37
|
+
⚠ .gitignore 시크릿 누락 Y건
|
|
38
|
+
→ 자동 수정: leerness audit --fix · 상세: leerness env check / leerness audit
|
|
39
|
+
```
|
|
40
|
+
- 끄기: `--no-security-summary` 또는 `--compact` (compact mode와 자동 통합).
|
|
41
|
+
|
|
42
|
+
### Use Case
|
|
43
|
+
- AI 에이전트가 **세션 시작 시 즉시 보안 위험 인지** — 사용자에게 명시적으로 알리고 자동 수정 제안.
|
|
44
|
+
|
|
45
|
+
### Verified
|
|
46
|
+
- stress-v22 — 보안 요약 노출 / 정상 시 OK / --no-security-summary + 누적 회귀.
|
|
47
|
+
- e2e 219/219 PASS 유지.
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
3
51
|
## 1.9.75 — 2026-05-20
|
|
4
52
|
|
|
5
53
|
**`leerness audit` 보안 강화 — `.gitignore` 시크릿 패턴 자동 검증** (사용자 글로벌 룰 ".gitignore 보안 체크리스트" 정책 자동화).
|
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.77 AI Agent Reliability Harness ║
|
|
16
16
|
║ verify · remember · orchestrate · audit · prevent drift ║
|
|
17
17
|
╚══════════════════════════════════════════════════════════════╝
|
|
18
18
|
```
|
|
@@ -433,6 +433,8 @@ npm test # = node ./scripts/e2e.js
|
|
|
433
433
|
|
|
434
434
|
## 변경 이력 (최근)
|
|
435
435
|
|
|
436
|
+
- **1.9.77** — **MCP server 15번째 도구 `leerness_brainstorm`** — 1.9.72 brainstorm (decisions + skills + tasks + rules + evidence + lessons + skillHistory + taskLogFails)을 외부 AI에 노출. AI가 새 작업 시작 전 누적 컨텍스트 자동 회수.
|
|
437
|
+
- **1.9.76** — **`leerness handoff`에 보안 상태 요약 자동 표시** — `.env→.env.example` 누락 + `.gitignore` 시크릿 패턴 누락을 매 handoff에 1-2 line 자동 노출. AI가 세션 시작 즉시 보안 위험 인지.
|
|
436
438
|
- **1.9.75** — **`leerness audit` 보안 강화** — `.env` 존재 시 `.gitignore`에 시크릿 패턴 (`.env`/`.env.local`/`.env.production`/`*.pem`/`credentials.json`) 자동 검증, `--fix`로 자동 추가.
|
|
437
439
|
- **1.9.74** — **`session close` 마감 시 누적 회고 통계 강화** — MCP tools/call 카운트 + skill match query top + drift 통계를 자동 요약 (1.9.70 + 1.9.68 결합).
|
|
438
440
|
- **1.9.73** — **MCP server 14번째 도구 `leerness_env_check`** — 1.9.71 env 보안 검사를 외부 AI에 노출 (외부 워크스페이스 .env/.env.example 동기화 자동 점검).
|
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.77';
|
|
10
10
|
const MARK = '<!-- leerness:managed -->';
|
|
11
11
|
const README_START = '<!-- leerness:project-readme:start -->';
|
|
12
12
|
const README_END = '<!-- leerness:project-readme:end -->';
|
|
@@ -1930,6 +1930,40 @@ function handoff(root) {
|
|
|
1930
1930
|
}
|
|
1931
1931
|
} catch {}
|
|
1932
1932
|
}
|
|
1933
|
+
// 1.9.76: handoff 보안 상태 요약 — .env vs .env.example + .gitignore 시크릿 패턴 1줄 요약
|
|
1934
|
+
// 매 세션 시작 시 AI가 보안 위험을 즉시 인지. --no-security-summary 또는 --compact로 끄기
|
|
1935
|
+
if (!has('--no-security-summary') && !has('--compact')) {
|
|
1936
|
+
try {
|
|
1937
|
+
const envExists = exists(path.join(root, '.env'));
|
|
1938
|
+
if (envExists) {
|
|
1939
|
+
const issues = [];
|
|
1940
|
+
// 1) env diff
|
|
1941
|
+
try {
|
|
1942
|
+
const d = envDiff(root);
|
|
1943
|
+
if (d.inEnvOnly.length) issues.push(`.env→.env.example 누락 ${d.inEnvOnly.length}건`);
|
|
1944
|
+
} catch {}
|
|
1945
|
+
// 2) gitignore 시크릿 패턴
|
|
1946
|
+
try {
|
|
1947
|
+
const gi = path.join(root, '.gitignore');
|
|
1948
|
+
const giText = exists(gi) ? read(gi) : '';
|
|
1949
|
+
const giLines = giText.split('\n').map(l => l.trim());
|
|
1950
|
+
const SECRET_PATTERNS = ['.env', '.env.local', '.env.production', '.env.*.local', '*.pem', 'credentials.json'];
|
|
1951
|
+
const missing = SECRET_PATTERNS.filter(p => !giLines.some(l => l === p || l === '/' + p));
|
|
1952
|
+
if (missing.length) issues.push(`.gitignore 시크릿 누락 ${missing.length}건`);
|
|
1953
|
+
} catch {}
|
|
1954
|
+
if (issues.length) {
|
|
1955
|
+
const isTty = process.stdout && process.stdout.isTTY;
|
|
1956
|
+
const red = s => isTty ? `\x1b[31m${s}\x1b[0m` : s;
|
|
1957
|
+
const dim = s => isTty ? `\x1b[2m${s}\x1b[0m` : s;
|
|
1958
|
+
log('');
|
|
1959
|
+
log(red(`## 🔒 보안 요약 (1.9.76) — ${issues.length}건 주의`));
|
|
1960
|
+
for (const i of issues) log(dim(` ⚠ ${i}`));
|
|
1961
|
+
log(dim(` → 자동 수정: leerness audit --fix · 상세: leerness env check / leerness audit`));
|
|
1962
|
+
log('');
|
|
1963
|
+
}
|
|
1964
|
+
}
|
|
1965
|
+
} catch {}
|
|
1966
|
+
}
|
|
1933
1967
|
// 1.9.41: 최근 migrate 차분 알림 — migration-report.md가 24h 내면 "AI must re-read" 블록 자동 표시
|
|
1934
1968
|
// 같은 채팅 세션의 AI 청크가 이전 버전 마인드셋이어도 새 도구를 즉시 인지하도록.
|
|
1935
1969
|
if (!has('--no-workflow-guide') && !has('--compact')) {
|
|
@@ -3275,7 +3309,7 @@ function _banner(opts = {}) {
|
|
|
3275
3309
|
lines.push('');
|
|
3276
3310
|
for (const ln of lines) log(ln);
|
|
3277
3311
|
if (opts.quickStart) {
|
|
3278
|
-
log(C.bold(C.cyan(' ✨ 빠른 시작 (1.9.
|
|
3312
|
+
log(C.bold(C.cyan(' ✨ 빠른 시작 (1.9.77+ 워크플로)')));
|
|
3279
3313
|
log(' ' + C.green('npx leerness@latest init .') + C.dim(' # 신규 프로젝트 + 외부 AI CLI 설정'));
|
|
3280
3314
|
log(' ' + C.green('npx leerness handoff .') + C.dim(' # 컨텍스트 + lessons + 매칭 skill + 이전 history hit (1.9.69)'));
|
|
3281
3315
|
log(' ' + C.green('npx leerness skill match "<query>"') + C.dim(' # 매칭 skill + rolling history 자동 누적 (1.9.68)'));
|
|
@@ -3284,7 +3318,7 @@ function _banner(opts = {}) {
|
|
|
3284
3318
|
log(' ' + C.green('npx leerness session close .') + C.dim(' # 마감 + 다음 라운드 추천 (default)'));
|
|
3285
3319
|
log('');
|
|
3286
3320
|
log(C.bold(C.cyan(' 🤖 메인 에이전트 (Claude/Cursor/Copilot)용')));
|
|
3287
|
-
log(' ' + C.green('npx leerness mcp serve') + C.dim(' # MCP 서버 —
|
|
3321
|
+
log(' ' + C.green('npx leerness mcp serve') + C.dim(' # MCP 서버 — 15 도구 (brainstorm 포함, 1.9.77)'));
|
|
3288
3322
|
log(' ' + C.green('npx leerness agents bench "<task>"') + C.dim(' # 3 CLI 동시 비교'));
|
|
3289
3323
|
log('');
|
|
3290
3324
|
}
|
|
@@ -7140,7 +7174,8 @@ function mcpServeCmd(root) {
|
|
|
7140
7174
|
{ name: 'leerness_skill_suggest', description: '1.9.53 — 사용 패턴 자동 분석 → 새 skill 후보 제안 (Hermes-style 자동 학습)', inputSchema: { type: 'object', properties: { path: { type: 'string' }, min: { type: 'number' }, days: { type: 'number' } } } },
|
|
7141
7175
|
{ name: 'leerness_lessons', description: '1.9.7/54 — 과거 결정·실수 자동 회수 (--auto: 현재 task 키워드 자동 추출)', inputSchema: { type: 'object', properties: { path: { type: 'string' }, query: { type: 'string' }, auto: { type: 'boolean' }, limit: { type: 'number' } } } },
|
|
7142
7176
|
{ name: 'leerness_task_export', description: '1.9.60/66 — leerness task → Claude Code TodoWrite 호환 JSON (외부 AI 양방향 sync)', inputSchema: { type: 'object', properties: { path: { type: 'string' }, to: { type: 'string' } } } },
|
|
7143
|
-
{ name: 'leerness_env_check', description: '1.9.71/73 — .env vs .env.example 동기화 검사 (보안: 키만, 값 미노출). exit 1 if 누락 키 있음', inputSchema: { type: 'object', properties: { path: { type: 'string' } } } }
|
|
7177
|
+
{ name: 'leerness_env_check', description: '1.9.71/73 — .env vs .env.example 동기화 검사 (보안: 키만, 값 미노출). exit 1 if 누락 키 있음', inputSchema: { type: 'object', properties: { path: { type: 'string' } } } },
|
|
7178
|
+
{ name: 'leerness_brainstorm', description: '1.9.16/72/77 — 누적 컨텍스트(decisions+skills+tasks+rules+evidence+lessons+skillHistory+taskLogFails) 자원 회수. 외부 AI가 새 작업 시작 전 호출', inputSchema: { type: 'object', properties: { topic: { type: 'string' }, path: { type: 'string' }, allApps: { type: 'boolean' } }, required: ['topic'] } }
|
|
7144
7179
|
];
|
|
7145
7180
|
|
|
7146
7181
|
function send(obj) {
|
|
@@ -7186,6 +7221,7 @@ function mcpServeCmd(root) {
|
|
|
7186
7221
|
case 'leerness_lessons': cliArgs = ['lessons', '--path', targetPath, ...(args.auto ? ['--auto'] : []), ...(args.query ? ['--query', args.query] : []), ...(args.limit ? ['--limit', String(args.limit)] : [])]; break;
|
|
7187
7222
|
case 'leerness_task_export': cliArgs = ['task', 'export', '--path', targetPath, ...(args.to ? ['--to', args.to] : ['--json'])]; break;
|
|
7188
7223
|
case 'leerness_env_check': cliArgs = ['env', 'check', targetPath, '--json']; break;
|
|
7224
|
+
case 'leerness_brainstorm': cliArgs = ['brainstorm', args.topic || '', '--path', targetPath, '--json', ...(args.allApps ? ['--all-apps'] : [])]; break;
|
|
7189
7225
|
default:
|
|
7190
7226
|
return send({ jsonrpc: '2.0', id, error: { code: -32601, message: `Unknown tool: ${name}` } });
|
|
7191
7227
|
}
|