leerness 1.9.79 → 1.9.80

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,27 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.9.80 — 2026-05-20
4
+
5
+ **handoff에서 `.env` 보안 critical 시 자동 회복 옵션** (1.9.76 보안 요약 + 1.9.75 audit --fix 결합).
6
+
7
+ ### Added — 보안 critical 자동 회복
8
+ - 1.9.76 handoff 보안 요약 블록 확장:
9
+ - `.env` 가 `.gitignore` 에 없으면 **🚨 CRITICAL** 경고.
10
+ - 즉시 `leerness audit --fix` 권장 안내.
11
+ - **자동 실행 옵션**: `LEERNESS_AUTO_SECURITY_FIX=1` 환경변수 활성 시 handoff에서 `audit --fix` 자동 실행.
12
+ - 시크릿 노출 위험 즉시 회복.
13
+ - 성공 시 `✓ 자동 회복 (LEERNESS_AUTO_SECURITY_FIX=1)` 메시지.
14
+
15
+ ### Use Case
16
+ - 사용자가 `.env` 를 무심코 만들었지만 `.gitignore` 에 추가 안 한 상태 → 다음 handoff에서 즉시 인지 + 옵션 활성 시 자동 회복.
17
+ - 1.9.78 drift 보안 신호 + 1.9.76 handoff 요약 + 1.9.80 자동 회복 = **3중 보안 가드** 완성.
18
+
19
+ ### Verified
20
+ - stress-v26 — handoff CRITICAL 메시지 / 자동 회복 / 누적 회귀.
21
+ - e2e 219/219 PASS 유지.
22
+
23
+ ---
24
+
3
25
  ## 1.9.79 — 2026-05-20
4
26
 
5
27
  **`leerness skill suggest` 알고리즘 강화** (1.9.68 rolling history 빈도 활용 — Hermes-style 학습 신호 보강).
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.79-green)]() [![tests](https://img.shields.io/badge/e2e-219%2F219-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.80-green)]() [![tests](https://img.shields.io/badge/e2e-219%2F219-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.79 AI Agent Reliability Harness ║
15
+ ║ v1.9.80 AI Agent Reliability Harness ║
16
16
  ║ verify · remember · orchestrate · audit · prevent drift ║
17
17
  ╚══════════════════════════════════════════════════════════════╝
18
18
  ```
@@ -433,6 +433,7 @@ npm test # = node ./scripts/e2e.js
433
433
 
434
434
  ## 변경 이력 (최근)
435
435
 
436
+ - **1.9.80** — **handoff 보안 critical 자동 회복** — `.env` 가 `.gitignore` 에 없으면 🚨 CRITICAL 경고 + `LEERNESS_AUTO_SECURITY_FIX=1` 시 `audit --fix` 자동 실행.
436
437
  - **1.9.79** — **`leerness skill suggest` 알고리즘 강화** — 1.9.68 rolling history 빈도 (×2 가중) 추가. 반복 검색된 키워드를 신규 skill 후보로 자동 식별 (Hermes-style 학습).
437
438
  - **1.9.78** — **`drift check` 5번째 신호** — `.env` + `.gitignore` 보안 누락을 drift score에 가중 (`.env` 자체 누락 시 +30, 동기화 누락 +15). 보안 위험이 drift critical 승격 가능.
438
439
  - **1.9.77** — **MCP server 15번째 도구 `leerness_brainstorm`** — 1.9.72 brainstorm (decisions + skills + tasks + rules + evidence + lessons + skillHistory + taskLogFails)을 외부 AI에 노출. AI가 새 작업 시작 전 누적 컨텍스트 자동 회수.
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.79';
9
+ const VERSION = '1.9.80';
10
10
  const MARK = '<!-- leerness:managed -->';
11
11
  const README_START = '<!-- leerness:project-readme:start -->';
12
12
  const README_END = '<!-- leerness:project-readme:end -->';
@@ -1955,10 +1955,35 @@ function handoff(root) {
1955
1955
  const isTty = process.stdout && process.stdout.isTTY;
1956
1956
  const red = s => isTty ? `\x1b[31m${s}\x1b[0m` : s;
1957
1957
  const dim = s => isTty ? `\x1b[2m${s}\x1b[0m` : s;
1958
+ const yel = s => isTty ? `\x1b[33m${s}\x1b[0m` : s;
1958
1959
  log('');
1959
1960
  log(red(`## 🔒 보안 요약 (1.9.76) — ${issues.length}건 주의`));
1960
1961
  for (const i of issues) log(dim(` ⚠ ${i}`));
1961
1962
  log(dim(` → 자동 수정: leerness audit --fix · 상세: leerness env check / leerness audit`));
1963
+ // 1.9.80: critical 수준 (.gitignore에 .env 자체 누락) 시 자동 회복 옵션
1964
+ const giText = exists(path.join(root, '.gitignore')) ? read(path.join(root, '.gitignore')) : '';
1965
+ const giLines = giText.split('\n').map(l => l.trim());
1966
+ const envInGitignore = giLines.includes('.env') || giLines.includes('/.env');
1967
+ if (!envInGitignore) {
1968
+ // .env 자체 누락 → 최우선 위험
1969
+ log(yel(` 🚨 CRITICAL (1.9.80): .env가 .gitignore에 없습니다! 시크릿 노출 위험 — 즉시 \`leerness audit --fix\` 권장.`));
1970
+ // LEERNESS_AUTO_SECURITY_FIX=1 자동 실행 옵션
1971
+ if (process.env.LEERNESS_AUTO_SECURITY_FIX === '1') {
1972
+ try {
1973
+ const r = cp.spawnSync(process.execPath, [__filename, 'audit', root, '--fix'],
1974
+ { encoding: 'utf8', timeout: 15000, env: { ...process.env, LEERNESS_NO_PROMPT: '1', LEERNESS_NO_DRIFT_CHECK: '1' } });
1975
+ if (r.status === 0) {
1976
+ log(dim(` ✓ 자동 회복 (LEERNESS_AUTO_SECURITY_FIX=1): audit --fix 완료`));
1977
+ } else {
1978
+ log(dim(` ⚠ 자동 회복 실패 (exit ${r.status}) — 수동 \`leerness audit --fix\` 권장`));
1979
+ }
1980
+ } catch (e) {
1981
+ log(dim(` ⚠ 자동 회복 예외: ${e.message}`));
1982
+ }
1983
+ } else {
1984
+ log(dim(` 💡 자동 실행 옵션: LEERNESS_AUTO_SECURITY_FIX=1 leerness handoff .`));
1985
+ }
1986
+ }
1962
1987
  log('');
1963
1988
  }
1964
1989
  }
@@ -3309,7 +3334,7 @@ function _banner(opts = {}) {
3309
3334
  lines.push('');
3310
3335
  for (const ln of lines) log(ln);
3311
3336
  if (opts.quickStart) {
3312
- log(C.bold(C.cyan(' ✨ 빠른 시작 (1.9.79+ 워크플로)')));
3337
+ log(C.bold(C.cyan(' ✨ 빠른 시작 (1.9.80+ 워크플로)')));
3313
3338
  log(' ' + C.green('npx leerness@latest init .') + C.dim(' # 신규 프로젝트 + 외부 AI CLI 설정'));
3314
3339
  log(' ' + C.green('npx leerness handoff .') + C.dim(' # 컨텍스트 + lessons + 매칭 skill + 이전 history hit (1.9.69)'));
3315
3340
  log(' ' + C.green('npx leerness skill match "<query>"') + C.dim(' # 매칭 skill + rolling history 자동 누적 (1.9.68)'));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "leerness",
3
- "version": "1.9.79",
3
+ "version": "1.9.80",
4
4
  "description": "Leerness: 비파괴 마이그레이션, 자동 버전 감지·업데이트, 계획/진행/핸드오프 자동화, 게으름·시크릿·인코딩 자동 가드, Claude Code 슬래시 통합을 갖춘 한국어 우선 AI 개발 하네스.",
5
5
  "keywords": [
6
6
  "leerness",