leerness 1.9.262 → 1.9.264

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,41 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.9.264 — 2026-06-01 — shellGuard JSON 12번째 통합 필드 (handoff/session close/health) + session close 본문 셸 요약
4
+
5
+ **🐚 UR-0020 셸 실패 메모리를 `--json` 표면 3 명령에 일관되게 통합 — 외부 AI/자동화가 셸 호환성 상태를 구조적으로 소비.**
6
+
7
+ ### 배경
8
+ 1.9.263에서 셸 실패 메모리를 handoff *본문 텍스트*에 노출했으나, `--json` 표면에는 없어 외부 AI/CI 가 구조적으로 못 읽음. leerness JSON 표면은 handoff/session close/health 3 명령이 동일 필드를 carry 하는 일관성 패턴(1.9.227/230/234 등)이 확립돼 있음 — `shellGuard` 를 12번째 필드로 추가해 그 패턴을 완성.
9
+
10
+ ### 구현
11
+ 1. **`shellGuard` JSON 12번째 통합 필드** — handoff/session close/health 3 명령 모두 동일 스키마:
12
+ - `failureCount` · `recent`(최근 3건: cmd 50자/exitCode/shell/rules) · `envDriftChanges` · `envDrift`(node/PS 버전 변동 배열 또는 null)
13
+ 2. **session close 본문 셸 요약** (1.9.217 통합 보고에 추가): 실패 누적 시 "🐚 셸 실패 누적 N건 — 다음 handoff 가 자동 노출" + env drift 경고, 깨끗하면 "✓ 셸 실패 기록 없음". `_loadShellFailures`/`_shellEnvDrift` 재사용 (1.9.263 export).
14
+
15
+ ### stress-v209 — **22/22 PASS · 100%**
16
+ - 1.9.264 (9): shellGuard 스키마·실패 반영·3 명령 일관성·envDrift 반영·session close 본문 노출/비노출
17
+ - 성능 (2): cold start avg 403ms · handoff --json 1540ms
18
+ - 누적 회귀 (11): 1.9.207~263 (handoff 본문 셸 가드·JSON 12 필드·MCP 72·shell-guard·selftest 15·require.main·path-setup·CJK·_isSecretKey·posixEncoding)
19
+
20
+ ## 1.9.263 — 2026-06-01 — UR-0020 3단계: handoff 셸 실패 메모리 + 환경 버전 변동 자동 노출
21
+
22
+ **🐚 과거 터미널 셸 실패 기록 + 환경 버전 변동을 매 세션 handoff 본문에 자동 표면화 (사용자 명시 UR-0020 완성).**
23
+
24
+ ### 배경
25
+ UR-0020 1·2단계에서 shell-guard 린터(6 규칙)·실패 메모리(`.harness/shell-failures.json`)·MCP 도구(72번째)를 구축했으나, 기록된 실패가 handoff 본문에 자동 노출되지 않아 새 세션 AI 가 "과거에 `&&` 가 실패했다"는 맥락을 능동적으로 못 봄. 사용자 요청 핵심("다음 터미널 실행 시 과거 실패를 고려")을 완성하려면 handoff 자동 표면화가 필요.
26
+
27
+ ### 구현
28
+ 1. **handoff 본문 셸 가드 섹션** (`## 🐚 터미널 셸 가드`): 기록된 셸 실패가 있거나 환경 버전이 변동되면 자동 노출
29
+ - `_loadShellFailures(root)` — 최근 3건 표시 (명령 50자 + exit code + shell + 감지 규칙)
30
+ - `_shellEnvDrift(root)` — `environment.json` 스냅샷 ↔ 현재 비교 (node·PowerShell 버전 변동 시 "과거 실패 재검토 권장" 경고)
31
+ - 실패·변동이 모두 없으면 섹션 미노출 (false-positive 차단)
32
+ 2. **exports 확대**: `_shellFailuresPath`·`_loadShellFailures`·`_recordShellFailure`·`_shellEnvDrift` 4종 → 단위 테스트 가능 (require.main 가드로 init 미실행)
33
+
34
+ ### stress-v208 — **25/25 PASS · 100%**
35
+ - 1.9.263 (12): exports 4종·경로·빈 워크스페이스·기록·200 cap·env drift null/변동 감지·CLI record 영속·handoff 노출/비노출/drift 경고
36
+ - 성능 (2): cold start avg 391ms · 200건 write 104ms
37
+ - 누적 회귀 (11): 1.9.207~262 (MCP 72·shell-guard·selftest 15·require.main 가드·path-setup·handoff JSON 11·posixEncoding·CJK·_isSecretKey·shell-guard summary)
38
+
3
39
  ## 1.9.262 — 2026-05-31 — CLAUDE/AGENTS 문서 누적 갱신 (1.9.253~261 drift 차단)
4
40
 
5
41
  **📚 메타 지침서가 1.9.252 에 멈춰 있어 9 라운드(1.9.253~261) 미반영 → 누적 갱신.**
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.262-green)]() [![tests](https://img.shields.io/badge/e2e-217%2F217-success)]() [![stress](https://img.shields.io/badge/stress--v207-20%2F20-success)]() [![mcp](https://img.shields.io/badge/MCP--tools-72-brightgreen)]() [![cli](https://img.shields.io/badge/CLI_commands-59-brightgreen)]() [![json-fields](https://img.shields.io/badge/JSON_통합-11_필드-blueviolet)]() [![rounds](https://img.shields.io/badge/autonomous_R-218-blueviolet)]() [![main-push](https://img.shields.io/badge/🎉_main--push_streak-124_rounds-success)]() [![npm-streak](https://img.shields.io/badge/🎉_npm--publish-85_streak-success)]() [![encoding](https://img.shields.io/badge/🌐_인코딩보호-Windows%2BPOSIX-blueviolet)]() [![perf](https://img.shields.io/badge/cold_start-368ms-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.264-green)]() [![tests](https://img.shields.io/badge/e2e-217%2F217-success)]() [![stress](https://img.shields.io/badge/stress--v209-22%2F22-success)]() [![mcp](https://img.shields.io/badge/MCP--tools-72-brightgreen)]() [![cli](https://img.shields.io/badge/CLI_commands-59-brightgreen)]() [![json-fields](https://img.shields.io/badge/JSON_통합-12_필드-blueviolet)]() [![rounds](https://img.shields.io/badge/autonomous_R-220-blueviolet)]() [![main-push](https://img.shields.io/badge/🎉_main--push_streak-126_rounds-success)]() [![npm-streak](https://img.shields.io/badge/🎉_npm--publish-87_streak-success)]() [![encoding](https://img.shields.io/badge/🌐_인코딩보호-Windows%2BPOSIX-blueviolet)]() [![perf](https://img.shields.io/badge/cold_start-403ms-success)]() [![license](https://img.shields.io/badge/license-MIT-lightgrey)]()
6
6
 
7
7
  ```
8
8
  ╔══════════════════════════════════════════════════════════════╗
@@ -12,9 +12,9 @@
12
12
  ║ ██║ ██╔══╝ ██╔══╝ ██╔══██╗██║╚██╗██║██╔══╝ ╚════██║ ║
13
13
  ║ ███████╗███████╗███████╗██║ ██║██║ ╚████║███████╗███████║ ║
14
14
  ║ ╚══════╝╚══════╝╚══════╝╚═╝ ╚═╝╚═╝ ╚═══╝╚══════╝╚══════╝ ║
15
- ║ v1.9.262 AI Agent Reliability Harness + Sandbox ║
15
+ ║ v1.9.264 AI Agent Reliability Harness + Sandbox ║
16
16
  ║ verify · remember · orchestrate · audit · sandbox · drift ║
17
- 📚 AI 핸드오프 지침 최신화 (1.9.253~261 · R218)
17
+ 🐚 shellGuard JSON 12필드 통합 (3 명령 일관성 · R220)
18
18
  ╚══════════════════════════════════════════════════════════════╝
19
19
  ```
20
20
 
package/bin/harness.js CHANGED
@@ -7,7 +7,7 @@ const cp = require('child_process');
7
7
  const os = require('os'); // 1.9.178: _publishToNpm 에서 os.tmpdir() 사용 (전역 import)
8
8
  const readline = require('readline');
9
9
 
10
- const VERSION = '1.9.262';
10
+ const VERSION = '1.9.264';
11
11
 
12
12
  // 1.9.184: DEP0190 (child_process shell: true) deprecation warning 억제 (사용자 명시).
13
13
  // leerness 는 cross-platform PATH resolution 을 위해 shell: true 를 의도적으로 사용 (claude.cmd / ollama.cmd 등 Windows .cmd 처리).
@@ -7515,6 +7515,17 @@ function handoff(root) {
7515
7515
  ids: allSkills.slice(0, 10).map(s => s.id)
7516
7516
  };
7517
7517
  } catch {}
7518
+ // 1.9.264: shellGuard 통합 (handoff JSON 12번째 통합 필드) — UR-0020 셸 실패 메모리 + 환경 변동 외부 회수
7519
+ try {
7520
+ const sf = _loadShellFailures(root);
7521
+ const drift = _shellEnvDrift(root);
7522
+ result.shellGuard = {
7523
+ failureCount: sf.failures.length,
7524
+ recent: sf.failures.slice(-3).map(f => ({ cmd: (f.cmd || '').slice(0, 50), exitCode: f.exitCode, shell: f.shell, rules: f.issues || [] })),
7525
+ envDriftChanges: drift && drift.changes ? drift.changes.length : 0,
7526
+ envDrift: drift ? drift.changes : null
7527
+ };
7528
+ } catch {}
7518
7529
  } catch {}
7519
7530
  try {
7520
7531
  const pwState = _loadPreWakeReport(root);
@@ -7913,6 +7924,35 @@ function handoff(root) {
7913
7924
  }
7914
7925
  } catch {}
7915
7926
 
7927
+ // 1.9.263 (UR-0020 3단계): handoff body 에 터미널 셸 실패 메모리 + 환경 버전 변동 자동 노출.
7928
+ // 새 세션 AI 가 과거 셸 명령 실패(예: PowerShell 5.1 && 미지원)를 즉시 인지 → 같은 실패 반복 차단.
7929
+ try {
7930
+ const sf = _loadShellFailures(root);
7931
+ const drift = _shellEnvDrift(root);
7932
+ const hasFailures = sf.failures && sf.failures.length > 0;
7933
+ const hasDrift = drift && drift.changes && drift.changes.length > 0;
7934
+ if (hasFailures || hasDrift) {
7935
+ const isTty8 = process.stdout && process.stdout.isTTY;
7936
+ const yl8 = s => isTty8 ? `\x1b[33m${s}\x1b[0m` : s;
7937
+ const dm8 = s => isTty8 ? `\x1b[2m${s}\x1b[0m` : s;
7938
+ const cy8 = s => isTty8 ? `\x1b[36m${s}\x1b[0m` : s;
7939
+ log('');
7940
+ log(cy8(`## 🐚 터미널 셸 가드 (1.9.263, UR-0020)`));
7941
+ if (hasDrift) {
7942
+ log(yl8(` ⚠ 환경 버전 변동 — 과거 셸 실패 기록 재검토 권장:`));
7943
+ drift.changes.forEach(ch => log(dm8(` ${ch.what}: ${ch.from} → ${ch.to}`)));
7944
+ }
7945
+ if (hasFailures) {
7946
+ log(dm8(` 최근 셸 실패 ${sf.failures.length}건 (최대 3 표시):`));
7947
+ sf.failures.slice(-3).reverse().forEach(f => {
7948
+ const rules = (f.issues && f.issues.length) ? ` [${f.issues.join(',')}]` : '';
7949
+ log(dm8(` • ${(f.cmd || '').slice(0, 50)} (exit=${f.exitCode}, ${f.shell})${rules}`));
7950
+ });
7951
+ log(dm8(` → 명령 실행 전 점검: leerness shell-guard "<command>"`));
7952
+ }
7953
+ }
7954
+ } catch {}
7955
+
7916
7956
  // 1.9.245: API skill cache 자동 참조 (사용자 명시 UR-0015)
7917
7957
  // 현재 task 키워드 기반으로 .harness/api-skills/ 매칭 → 사용자가 정리해둔 API 문서 자동 노출
7918
7958
  try {
@@ -11849,6 +11889,17 @@ function sessionClose(root, opts = {}) {
11849
11889
  ids: allSkills.slice(0, 10).map(s => s.id)
11850
11890
  };
11851
11891
  } catch {}
11892
+ // 1.9.264: shellGuard 통합 (session close JSON 12번째 통합 필드) — UR-0020 셸 실패 메모리 + 환경 변동
11893
+ try {
11894
+ const sf = _loadShellFailures(root);
11895
+ const drift = _shellEnvDrift(root);
11896
+ jsonResult.shellGuard = {
11897
+ failureCount: sf.failures.length,
11898
+ recent: sf.failures.slice(-3).map(f => ({ cmd: (f.cmd || '').slice(0, 50), exitCode: f.exitCode, shell: f.shell, rules: f.issues || [] })),
11899
+ envDriftChanges: drift && drift.changes ? drift.changes.length : 0,
11900
+ envDrift: drift ? drift.changes : null
11901
+ };
11902
+ } catch {}
11852
11903
  } catch {}
11853
11904
  try {
11854
11905
  // 1.9.209: pre-wake-audit 자동 실행 + 저장 (sleep 전 자동 점검)
@@ -11953,6 +12004,21 @@ function sessionClose(root, opts = {}) {
11953
12004
  log(grn(` ✓ 멱등성 검사 통과 — verified ${idemp.summary.verifiedAreas} 영역`));
11954
12005
  }
11955
12006
  } catch {}
12007
+ // 1.9.264: 셸 실패 메모리 + 환경 변동 요약 (UR-0020) — 마감 시 이번 세션 셸 실패를 회고에 노출
12008
+ try {
12009
+ const sf = _loadShellFailures(root);
12010
+ const drift = _shellEnvDrift(root);
12011
+ const driftN = drift && drift.changes ? drift.changes.length : 0;
12012
+ if (sf.failures.length > 0 || driftN > 0) {
12013
+ if (driftN > 0) log(yel(` ⚠ 환경 버전 변동 ${driftN}건 — 다음 세션 셸 실패 기록 재검토 권장`));
12014
+ if (sf.failures.length > 0) {
12015
+ log(yel(` 🐚 셸 실패 누적 ${sf.failures.length}건 — 다음 handoff 가 자동 노출`));
12016
+ log(dim(` → 명령 실행 전 점검: leerness shell-guard "<command>"`));
12017
+ }
12018
+ } else {
12019
+ log(grn(` ✓ 셸 실패 기록 없음 (터미널 호환성 양호)`));
12020
+ }
12021
+ } catch {}
11956
12022
  // 1.9.237: session close --auto-cleanup-branches — 50+ release/* branches 시 자동 정리
11957
12023
  // 1.9.224 패턴 (--auto-apply-delivered) 확장 — 마감 시 운영 누적 폐기물 자동 정리
11958
12024
  // 안전: keep 10, merged 만, 현재 branch 보호
@@ -18659,6 +18725,17 @@ function healthCmd(root) {
18659
18725
  ids: allSkills.slice(0, 10).map(s => s.id)
18660
18726
  };
18661
18727
  } catch { out.apiSkills = { error: 'apiSkills 점검 실패' }; }
18728
+ // 1.9.264: shellGuard 통합 (health JSON 12번째 통합 필드 — handoff/session close 와 JSON 3 명령 일관성) — UR-0020
18729
+ try {
18730
+ const sf = _loadShellFailures(root);
18731
+ const drift = _shellEnvDrift(root);
18732
+ out.shellGuard = {
18733
+ failureCount: sf.failures.length,
18734
+ recent: sf.failures.slice(-3).map(f => ({ cmd: (f.cmd || '').slice(0, 50), exitCode: f.exitCode, shell: f.shell, rules: f.issues || [] })),
18735
+ envDriftChanges: drift && drift.changes ? drift.changes.length : 0,
18736
+ envDrift: drift ? drift.changes : null
18737
+ };
18738
+ } catch { out.shellGuard = { error: 'shellGuard 점검 실패' }; }
18662
18739
  // 1.9.163: 5능력 매트릭스 자동 평가 (1.9.155 sub-agent 점검 → 코드 기반 자동화)
18663
18740
  // 각 능력을 코드 grep 으로 검출 → 0~100 점수. 사용자가 매 health 호출 시 leerness 자기 평가 확인.
18664
18741
  try {
@@ -20282,5 +20359,7 @@ module.exports = {
20282
20359
  // 1.9.258: selftest — 코어 함수 무결성 검증
20283
20360
  _selfTestCases, selfTestCmd,
20284
20361
  // 1.9.260: shell-guard — 셸 호환성 린터 (UR-0020) 순수 분석 함수 — 단위 테스트
20285
- _shellGuardAnalyze, _detectShellCtx, shellGuardCmd
20362
+ _shellGuardAnalyze, _detectShellCtx, shellGuardCmd,
20363
+ // 1.9.263: shell 실패 메모리 + 환경 버전 변동 (UR-0020 3단계) — handoff 통합 단위 테스트
20364
+ _shellFailuresPath, _loadShellFailures, _recordShellFailure, _shellEnvDrift
20286
20365
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "leerness",
3
- "version": "1.9.262",
3
+ "version": "1.9.264",
4
4
  "description": "Leerness: 비파괴 마이그레이션, 자동 버전 감지·업데이트, 계획/진행/핸드오프 자동화, 게으름·시크릿·인코딩 자동 가드, Claude Code 슬래시 통합을 갖춘 한국어 우선 AI 개발 하네스.",
5
5
  "keywords": [
6
6
  "leerness",