leerness 1.9.250 → 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 +66 -0
- package/README.md +3 -3
- package/bin/harness.js +66 -22
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,71 @@
|
|
|
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
|
+
|
|
35
|
+
## 1.9.251 — 2026-05-29 — UR-0018 3단계 init 터미널 인코딩 점검 안내
|
|
36
|
+
|
|
37
|
+
**🌐 UR-0018 완성: 자동 회복(1.9.249/250)에 이어 `leerness init` 시 사용자 즉시 고지.**
|
|
38
|
+
|
|
39
|
+
### 배경
|
|
40
|
+
UR-0018 원문에 명시된 *"leerness init 시 터미널 인코딩 점검 안내"* 부분이 미구현 상태. 1.9.249(Windows chcp)/1.9.250(POSIX)는 자동 회복에 집중했으나, 설치 직후 사용자에게 현재 인코딩 상태를 보여주는 가시화는 빠져 있었음.
|
|
41
|
+
|
|
42
|
+
### 구현
|
|
43
|
+
1. **`_terminalEncodingNotice()` 재사용 헬퍼 신설**:
|
|
44
|
+
- Windows(CP949) + POSIX(Linux/macOS/WSL) 양방향 점검을 한 곳에 통합
|
|
45
|
+
- 반환 `{ ok, lines[] }` — 색상 적용된 출력 라인 (호출측이 `log()`)
|
|
46
|
+
- TTY 자동 감지 → 비-TTY 시 색상 코드 생략
|
|
47
|
+
2. **`leerness init` 완료 시 자동 호출** (`!opts.migration` 가드):
|
|
48
|
+
- `🌐 터미널 인코딩 점검 (1.9.251, UR-0018)` 헤더 + 상태 라인
|
|
49
|
+
- 위험 시 `상세: leerness env · 셸 스크립트 검사: leerness env encoding` 안내
|
|
50
|
+
- 안전(65001/UTF-8) 시 `✓` 초록 표시
|
|
51
|
+
3. migration(재설치)에서는 노이즈 방지를 위해 skip
|
|
52
|
+
|
|
53
|
+
### 영향 받지 않은 영역
|
|
54
|
+
- 1.9.249 chcp 65001 자동 회복 + 1.9.250 POSIX posixEncodingOk/isWSL 모두 유지
|
|
55
|
+
- JSON envInfo 4 필드 (terminalEncodingOk/autoChcpApplied/posixEncodingOk/isWSL) 유지
|
|
56
|
+
- env summary 인라인 인코딩 라인 (1.9.249/250) 유지 — 헬퍼와 독립
|
|
57
|
+
|
|
58
|
+
### stress-v196 — **21/21 PASS · 100%**
|
|
59
|
+
- 1.9.251 (8): VERSION + 헬퍼 + 반환구조 + install 호출 + Windows/POSIX 분기 + migration skip + 실제 init 출력
|
|
60
|
+
- 성능 (1): cold start avg 471ms
|
|
61
|
+
- 누적 회귀 (12): 1.9.207~250
|
|
62
|
+
|
|
63
|
+
### 자동 release (113 main-push streak · 74 npm publish streak · R207)
|
|
64
|
+
|
|
65
|
+
🌐 **UR-0018 3단계 완성** — 자동 회복 + 설치 시 가시화로 한국어 인코딩 보호 전체 사이클 완결.
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
3
69
|
## 1.9.250 — 2026-05-28 — UR-0018 2단계 POSIX 인코딩 자동 회복 (Linux/macOS/WSL)
|
|
4
70
|
|
|
5
71
|
**🌐 UR-0018 후속: Windows + POSIX 양방향 인코딩 보호 완성.**
|
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,9 +12,9 @@
|
|
|
12
12
|
║ ██║ ██╔══╝ ██╔══╝ ██╔══██╗██║╚██╗██║██╔══╝ ╚════██║ ║
|
|
13
13
|
║ ███████╗███████╗███████╗██║ ██║██║ ╚████║███████╗███████║ ║
|
|
14
14
|
║ ╚══════╝╚══════╝╚══════╝╚═╝ ╚═╝╚═╝ ╚═══╝╚══════╝╚══════╝ ║
|
|
15
|
-
║ v1.9.
|
|
15
|
+
║ v1.9.251 AI Agent Reliability Harness + Sandbox ║
|
|
16
16
|
║ verify · remember · orchestrate · audit · sandbox · drift ║
|
|
17
|
-
║ 🌐 인코딩
|
|
17
|
+
║ 🌐 init 인코딩 점검 안내 (Windows+POSIX · UR-0018 3단계) ║
|
|
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.
|
|
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 처리).
|
|
@@ -1056,6 +1056,19 @@ async function install(root, opts = {}) {
|
|
|
1056
1056
|
}
|
|
1057
1057
|
} catch {}
|
|
1058
1058
|
}
|
|
1059
|
+
// 1.9.251 (UR-0018 3단계): init 완료 시 터미널 인코딩 점검 안내 — 사용자 명시 ("leerness init 시 터미널 인코딩 점검 안내")
|
|
1060
|
+
// Windows CP949 / POSIX non-UTF-8 환경에서 leerness 한국어 출력 깨짐을 설치 직후 사용자에게 즉시 고지.
|
|
1061
|
+
if (!opts.migration) {
|
|
1062
|
+
try {
|
|
1063
|
+
const enc = _terminalEncodingNotice();
|
|
1064
|
+
if (enc.lines.length > 0) {
|
|
1065
|
+
log('');
|
|
1066
|
+
log(`\x1b[36m🌐 터미널 인코딩 점검 (1.9.251, UR-0018)\x1b[0m`);
|
|
1067
|
+
enc.lines.forEach(l => log(l));
|
|
1068
|
+
if (!enc.ok) log(`\x1b[2m 상세: leerness env · 셸 스크립트 검사: leerness env encoding\x1b[0m`);
|
|
1069
|
+
}
|
|
1070
|
+
} catch {}
|
|
1071
|
+
}
|
|
1059
1072
|
// 1.9.1 P7: 디폴트 M-0001이 plan에 있고 progress에 row가 없으면 자동 추가
|
|
1060
1073
|
try {
|
|
1061
1074
|
const planText = exists(planPath(root)) ? read(planPath(root)) : '';
|
|
@@ -2345,6 +2358,14 @@ function agentModeCmd(root, sub) {
|
|
|
2345
2358
|
}
|
|
2346
2359
|
if (sub === 'start') {
|
|
2347
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 {}
|
|
2348
2369
|
log(dm(` → 1. drift check --auto-fix (보안 + delivered + release cleanup)`));
|
|
2349
2370
|
const r1 = spawnChild(['drift', 'check', root, '--auto-fix']);
|
|
2350
2371
|
if (r1.status === 0) log(gr(` ✓ drift auto-fix 완료`)); else log(yl(` ⚠ drift auto-fix 종료 ${r1.status}`));
|
|
@@ -2487,6 +2508,44 @@ function _collectRuntimeEnv() {
|
|
|
2487
2508
|
return env;
|
|
2488
2509
|
}
|
|
2489
2510
|
|
|
2511
|
+
// 1.9.251 (UR-0018 3단계): leerness init/명령 시 터미널 인코딩 점검 안내 (재사용 헬퍼)
|
|
2512
|
+
// Windows (CP949) + POSIX (Linux/macOS/WSL) 양방향 — leerness 한국어 출력 깨짐 사전 점검.
|
|
2513
|
+
// 반환: { ok, lines:[] } — lines 는 색상 적용된 출력 라인 배열 (호출측이 log() 로 출력).
|
|
2514
|
+
function _terminalEncodingNotice(opts = {}) {
|
|
2515
|
+
const isTty = opts.isTty != null ? opts.isTty : !!(process.stdout && process.stdout.isTTY);
|
|
2516
|
+
const gr = s => isTty ? `\x1b[32m${s}\x1b[0m` : s;
|
|
2517
|
+
const yl = s => isTty ? `\x1b[33m${s}\x1b[0m` : s;
|
|
2518
|
+
const dm = s => isTty ? `\x1b[2m${s}\x1b[0m` : s;
|
|
2519
|
+
const lines = [];
|
|
2520
|
+
let ok = true;
|
|
2521
|
+
let env;
|
|
2522
|
+
try { env = _collectRuntimeEnv(); } catch { return { ok: true, lines: [] }; }
|
|
2523
|
+
// Windows 한국어 + 비-65001 코드페이지
|
|
2524
|
+
if (env.locale.isKoreanWindows && env.locale.codepage !== 65001) {
|
|
2525
|
+
ok = false;
|
|
2526
|
+
lines.push(yl(` ⚠ 터미널 코드페이지 CP${env.locale.codepage} (CP949) — leerness 한국어 출력 깨짐 위험`));
|
|
2527
|
+
if (process.env._LEERNESS_AUTOCHCP_APPLIED) {
|
|
2528
|
+
lines.push(gr(` ✓ chcp 65001 자동 적용됨 (이전: ${process.env._LEERNESS_AUTOCHCP_APPLIED}, 1.9.249)`));
|
|
2529
|
+
} else {
|
|
2530
|
+
lines.push(dm(` → 수동: chcp 65001 (또는 자동: LEERNESS_NO_AUTOCHCP 미설정)`));
|
|
2531
|
+
}
|
|
2532
|
+
} else if (env.locale.codepage === 65001) {
|
|
2533
|
+
lines.push(gr(` ✓ 터미널 인코딩 UTF-8 (65001) — 한국어 출력 안전`));
|
|
2534
|
+
}
|
|
2535
|
+
// POSIX (Linux/macOS/WSL) locale UTF-8 점검
|
|
2536
|
+
if (env.locale.posixEncodingOk === false) {
|
|
2537
|
+
ok = false;
|
|
2538
|
+
const wslTag = env.locale.isWSL ? ' (WSL)' : '';
|
|
2539
|
+
lines.push(yl(` ⚠ POSIX${wslTag} locale에 UTF-8 없음 (LANG=${env.locale.LANG || 'unset'}) — 한국어 출력 깨질 위험`));
|
|
2540
|
+
lines.push(dm(` → 권장: export LANG=ko_KR.UTF-8 (또는 export LC_ALL=C.UTF-8)`));
|
|
2541
|
+
lines.push(dm(` → 영구: ~/.bashrc 또는 ~/.zshrc 에 추가`));
|
|
2542
|
+
} else if (env.locale.posixEncodingOk === true) {
|
|
2543
|
+
const wslTag = env.locale.isWSL ? ' (WSL)' : '';
|
|
2544
|
+
lines.push(gr(` ✓ POSIX locale UTF-8${wslTag} — 한국어 출력 안전`));
|
|
2545
|
+
}
|
|
2546
|
+
return { ok, lines };
|
|
2547
|
+
}
|
|
2548
|
+
|
|
2490
2549
|
// 셸 스크립트 (.ps1/.bat/.cmd/.sh) 인코딩 위험 감지
|
|
2491
2550
|
// 위험 시그널: 한국어 (또는 비-ASCII) 문자 + BOM 없음 + Windows 환경
|
|
2492
2551
|
function _scanShellScriptsEncoding(root) {
|
|
@@ -2626,27 +2685,12 @@ function envCmd(root, sub) {
|
|
|
2626
2685
|
log(` 💻 OS: ${gr(env.os.platform)} ${env.os.release} (${env.os.arch})`);
|
|
2627
2686
|
log(` 📦 Node: ${gr(env.node.version)}`);
|
|
2628
2687
|
log(` 🌐 Locale: LANG=${env.locale.LANG || 'unset'} · CP=${env.locale.codepage || 'unknown'}${env.locale.isKoreanWindows ? yl(' (한국어 Windows)') : ''}`);
|
|
2629
|
-
// 1.9.
|
|
2630
|
-
|
|
2631
|
-
|
|
2632
|
-
|
|
2633
|
-
|
|
2634
|
-
|
|
2635
|
-
log(dm(` → 수동: chcp 65001 (또는 LEERNESS_NO_AUTOCHCP=0)`));
|
|
2636
|
-
}
|
|
2637
|
-
} else if (env.locale.codepage === 65001) {
|
|
2638
|
-
log(gr(` ✓ 터미널 인코딩 UTF-8 (65001) — 한국어 출력 안전`));
|
|
2639
|
-
}
|
|
2640
|
-
// 1.9.250 (UR-0018 2단계): POSIX (Linux/macOS/WSL) terminal encoding 점검
|
|
2641
|
-
if (env.os.platform === 'linux' || env.os.platform === 'darwin') {
|
|
2642
|
-
const wslTag = env.locale.isWSL ? yl(' (WSL)') : '';
|
|
2643
|
-
if (env.locale.posixEncodingOk === true) {
|
|
2644
|
-
log(gr(` ✓ POSIX locale UTF-8 — ${env.os.platform === 'darwin' ? 'macOS' : 'Linux'}${wslTag} 한국어 출력 안전`));
|
|
2645
|
-
} else if (env.locale.posixEncodingOk === false) {
|
|
2646
|
-
log(yl(` ⚠ POSIX locale에 UTF-8 없음 (LANG=${env.locale.LANG || 'unset'}) — 한국어 출력 깨질 위험`));
|
|
2647
|
-
log(dm(` → 권장: export LANG=ko_KR.UTF-8 (또는 export LC_ALL=C.UTF-8)`));
|
|
2648
|
-
}
|
|
2649
|
-
}
|
|
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 {}
|
|
2650
2694
|
log(` 🖥 Hardware: ${env.hardware.cpus} CPUs · ${env.hardware.memGB} GB RAM`);
|
|
2651
2695
|
log(` 🖱 Terminal: TTY=${env.terminal.isTTY}${env.terminal.powershell ? ` · PowerShell v${env.terminal.powershell}` : ''}`);
|
|
2652
2696
|
log(` 🔧 Tools:`);
|