leerness 1.9.251 → 1.9.252

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,37 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.9.252 — 2026-05-29 — UR-0018 마무리: env DRY 통합 + agent-mode 인코딩 점검
4
+
5
+ **🧹 UR-0018 코드 정리: 1.9.249~251 누적된 인코딩 분기 중복을 단일 헬퍼로 일원화.**
6
+
7
+ ### 배경
8
+ 1.9.249(Windows)/1.9.250(POSIX)/1.9.251(헬퍼 신설) 진행 중, `env summary`에는 여전히 인라인 Windows/POSIX 분기가 중복으로 남아 있었음 (1.9.251에서 헬퍼는 만들었으나 env summary는 미적용). 코드 일관성(DRY)과 자율 모드 진입점 보강.
9
+
10
+ ### 구현
11
+ 1. **env summary DRY 통합**:
12
+ - 인라인 Windows(CP949) + POSIX(LANG UTF-8) 분기 ~20줄 → `_terminalEncodingNotice()` 단일 호출로 교체
13
+ - 출력 동일성 유지 (회귀 테스트 A6/A8로 검증) — 단일 소스로 일원화
14
+ 2. **agent-mode start 인코딩 점검 추가**:
15
+ - 자율 모드 진입(`leerness agent-mode start`) 시에도 인코딩 점검 (init과 동일 정책)
16
+ - `!enc.ok` 가드 — 위험할 때만 노출 (정상 환경 노이즈 0)
17
+ - `🌐 터미널 인코딩 점검 (1.9.252, UR-0018)` 헤더
18
+
19
+ ### 영향 받지 않은 영역
20
+ - _terminalEncodingNotice 헬퍼 (1.9.251) · install 호출 (1.9.251) 유지
21
+ - JSON envInfo 4 필드 (1.9.249/250) · IIFE chcp 자동회복 (1.9.249) 유지
22
+ - handoff JSON 11 필드 매트릭스 유지
23
+
24
+ ### stress-v197 — **21/21 PASS · 100%**
25
+ - 1.9.252 (8): VERSION + env DRY 통합 + 인라인 제거 검증 + agent-mode 점검 + 가드 + 출력 회귀 + 헬퍼 단일정의 + 구조 보존
26
+ - 성능 (1): cold start avg 394ms
27
+ - 누적 회귀 (12): 1.9.207~251
28
+
29
+ ### 자동 release (114 main-push streak · 75 npm publish streak · R208)
30
+
31
+ 🧹 **UR-0018 코드 일관성 완결** — 4 라운드(1.9.249~252) 누적 인코딩 로직을 단일 헬퍼로 정리, 진입점 3곳(init/agent-mode/env) 일관 적용.
32
+
33
+ ---
34
+
3
35
  ## 1.9.251 — 2026-05-29 — UR-0018 3단계 init 터미널 인코딩 점검 안내
4
36
 
5
37
  **🌐 UR-0018 완성: 자동 회복(1.9.249/250)에 이어 `leerness init` 시 사용자 즉시 고지.**
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.251-green)]() [![tests](https://img.shields.io/badge/e2e-217%2F217-success)]() [![stress](https://img.shields.io/badge/stress--v196-21%2F21-success)]() [![mcp](https://img.shields.io/badge/MCP--tools-70-brightgreen)]() [![cli](https://img.shields.io/badge/CLI_commands-57-brightgreen)]() [![json-fields](https://img.shields.io/badge/JSON_통합-11_필드-blueviolet)]() [![rounds](https://img.shields.io/badge/autonomous_R-207-blueviolet)]() [![main-push](https://img.shields.io/badge/🎉_main--push_streak-113_rounds-success)]() [![npm-streak](https://img.shields.io/badge/🎉_npm--publish-74_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.252-green)]() [![tests](https://img.shields.io/badge/e2e-217%2F217-success)]() [![stress](https://img.shields.io/badge/stress--v197-21%2F21-success)]() [![mcp](https://img.shields.io/badge/MCP--tools-70-brightgreen)]() [![cli](https://img.shields.io/badge/CLI_commands-57-brightgreen)]() [![json-fields](https://img.shields.io/badge/JSON_통합-11_필드-blueviolet)]() [![rounds](https://img.shields.io/badge/autonomous_R-208-blueviolet)]() [![main-push](https://img.shields.io/badge/🎉_main--push_streak-114_rounds-success)]() [![npm-streak](https://img.shields.io/badge/🎉_npm--publish-75_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)]()
6
6
 
7
7
  ```
8
8
  ╔══════════════════════════════════════════════════════════════╗
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.251';
10
+ const VERSION = '1.9.252';
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 처리).
@@ -2358,6 +2358,14 @@ function agentModeCmd(root, sub) {
2358
2358
  }
2359
2359
  if (sub === 'start') {
2360
2360
  log(cy(`# leerness agent-mode start (1.9.239)`));
2361
+ // 1.9.252 (UR-0018 마무리): 자율 모드 진입 시에도 터미널 인코딩 점검 (init 과 동일 — 한국어 출력 깨짐 사전 고지)
2362
+ try {
2363
+ const enc = _terminalEncodingNotice();
2364
+ if (!enc.ok && enc.lines.length > 0) {
2365
+ log(yl(` 🌐 터미널 인코딩 점검 (1.9.252, UR-0018)`));
2366
+ enc.lines.forEach(l => log(l));
2367
+ }
2368
+ } catch {}
2361
2369
  log(dm(` → 1. drift check --auto-fix (보안 + delivered + release cleanup)`));
2362
2370
  const r1 = spawnChild(['drift', 'check', root, '--auto-fix']);
2363
2371
  if (r1.status === 0) log(gr(` ✓ drift auto-fix 완료`)); else log(yl(` ⚠ drift auto-fix 종료 ${r1.status}`));
@@ -2677,27 +2685,12 @@ function envCmd(root, sub) {
2677
2685
  log(` 💻 OS: ${gr(env.os.platform)} ${env.os.release} (${env.os.arch})`);
2678
2686
  log(` 📦 Node: ${gr(env.node.version)}`);
2679
2687
  log(` 🌐 Locale: LANG=${env.locale.LANG || 'unset'} · CP=${env.locale.codepage || 'unknown'}${env.locale.isKoreanWindows ? yl(' (한국어 Windows)') : ''}`);
2680
- // 1.9.249 (UR-0018): 터미널 출력 인코딩 자동 점검 한국어 Windows + 비-65001 → 경고 + 자동 회복 결과
2681
- if (env.locale.isKoreanWindows && env.locale.codepage !== 65001) {
2682
- log(yl(` 터미널 코드페이지 ${env.locale.codepage} (CP949) — 한국어 출력 깨짐 위험`));
2683
- if (process.env._LEERNESS_AUTOCHCP_APPLIED) {
2684
- log(gr(` ✓ chcp 65001 자동 적용됨 (이전: ${process.env._LEERNESS_AUTOCHCP_APPLIED}, 1.9.249)`));
2685
- } else {
2686
- log(dm(` → 수동: chcp 65001 (또는 LEERNESS_NO_AUTOCHCP=0)`));
2687
- }
2688
- } else if (env.locale.codepage === 65001) {
2689
- log(gr(` ✓ 터미널 인코딩 UTF-8 (65001) — 한국어 출력 안전`));
2690
- }
2691
- // 1.9.250 (UR-0018 2단계): POSIX (Linux/macOS/WSL) terminal encoding 점검
2692
- if (env.os.platform === 'linux' || env.os.platform === 'darwin') {
2693
- const wslTag = env.locale.isWSL ? yl(' (WSL)') : '';
2694
- if (env.locale.posixEncodingOk === true) {
2695
- log(gr(` ✓ POSIX locale UTF-8 — ${env.os.platform === 'darwin' ? 'macOS' : 'Linux'}${wslTag} 한국어 출력 안전`));
2696
- } else if (env.locale.posixEncodingOk === false) {
2697
- log(yl(` ⚠ POSIX locale에 UTF-8 없음 (LANG=${env.locale.LANG || 'unset'}) — 한국어 출력 깨질 위험`));
2698
- log(dm(` → 권장: export LANG=ko_KR.UTF-8 (또는 export LC_ALL=C.UTF-8)`));
2699
- }
2700
- }
2688
+ // 1.9.252 (UR-0018 마무리): 인라인 Windows/POSIX 인코딩 분기를 _terminalEncodingNotice() 헬퍼로 통합 (DRY).
2689
+ // 이전 (1.9.249/250) 에는 env summary / handoff / install 에 거의 동일한 분기가 중복 → 단일 소스로 일원화.
2690
+ try {
2691
+ const enc = _terminalEncodingNotice();
2692
+ enc.lines.forEach(l => log(l));
2693
+ } catch {}
2701
2694
  log(` 🖥 Hardware: ${env.hardware.cpus} CPUs · ${env.hardware.memGB} GB RAM`);
2702
2695
  log(` 🖱 Terminal: TTY=${env.terminal.isTTY}${env.terminal.powershell ? ` · PowerShell v${env.terminal.powershell}` : ''}`);
2703
2696
  log(` 🔧 Tools:`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "leerness",
3
- "version": "1.9.251",
3
+ "version": "1.9.252",
4
4
  "description": "Leerness: 비파괴 마이그레이션, 자동 버전 감지·업데이트, 계획/진행/핸드오프 자동화, 게으름·시크릿·인코딩 자동 가드, Claude Code 슬래시 통합을 갖춘 한국어 우선 AI 개발 하네스.",
5
5
  "keywords": [
6
6
  "leerness",