leerness 1.9.32 → 1.9.33
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 +28 -0
- package/README.md +37 -2
- package/bin/harness.js +54 -2
- package/package.json +1 -1
- package/scripts/e2e.js +38 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,33 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.9.33 — 2026-05-15
|
|
4
|
+
|
|
5
|
+
**npx 캐시 함정 방지 — install 시 stale 버전 자동 경고 + 해결 안내**.
|
|
6
|
+
|
|
7
|
+
### 배경
|
|
8
|
+
사용자가 `npx leerness init`(@latest 없이)을 실행하면 npm/npx의 로컬 캐시에 있는 옛 버전이 무한히 재사용되는 함정이 있음. 1.9.32 publish 후에도 사용자 PC에서 1.9.21이 실행되는 사례 확인.
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- **`_warnIfStale()` 헬퍼**: `install()` 진입 시 자동 호출.
|
|
13
|
+
- npm registry latest 비교 (`fetchNpmLatest` + 24h cache 재사용)
|
|
14
|
+
- 현재 실행 중인 VERSION이 registry latest보다 옛날이면 ⚠ 노랑색 경고 박스 출력
|
|
15
|
+
- 해결 명령 2가지 안내: `npx --yes clear-npx-cache && npx leerness@latest init .` 또는 `npm i -g leerness@latest`
|
|
16
|
+
- **init 자체는 계속 진행** (경고만 띄움 — 강제 차단 X)
|
|
17
|
+
- **`--no-stale-check`** 플래그 + **`LEERNESS_NO_STALE_CHECK=1`** env 변수: 경고 스킵
|
|
18
|
+
- **offline + 캐시 없음**: 비교 스킵 (네트워크 차단 환경 안전)
|
|
19
|
+
- **offline + 캐시 fresh**: 캐시값으로 비교 (e2e 등 CI 환경에서도 동작)
|
|
20
|
+
|
|
21
|
+
### Policy
|
|
22
|
+
- ❌ 사용자 init 차단 안 함 (경고만, init은 계속 진행)
|
|
23
|
+
- ✅ 24h 캐시로 매 init마다 npm view 호출 안 함 (cold-start만 12s timeout)
|
|
24
|
+
- ✅ 네트워크 실패 시 silently skip — init 흐름 끊지 않음
|
|
25
|
+
- ✅ `--no-stale-check`/env로 끄기 가능 (CI 친화)
|
|
26
|
+
|
|
27
|
+
### 실측 (이번 라운드)
|
|
28
|
+
- 사용자 PC: `npx leerness init` → 1.9.21 실행됨 (npm latest=1.9.32) — 1.9.33부터 install 시 즉시 경고
|
|
29
|
+
- e2e: 153/153 PASS (1.9.32 151 + stale 경고/스킵 2)
|
|
30
|
+
|
|
3
31
|
## 1.9.32 — 2026-05-15
|
|
4
32
|
|
|
5
33
|
**ASCII 배너 + `leerness setup-agents` 인터랙티브 설정 + 미설치 CLI 자동 설치 시도**.
|
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
> 한국어 우선 AI 개발 하네스. 멀티 에이전트 오케스트레이션 · 자동 검수 · 워크스페이스 가시성 · Ollama opt-in 통합.
|
|
4
4
|
|
|
5
|
-
[](https://www.npmjs.com/package/leerness) [](https://www.npmjs.com/package/leerness) []() []() []()
|
|
6
6
|
|
|
7
7
|
```
|
|
8
8
|
╔══════════════════════════════════════════════════════════════╗
|
|
@@ -38,6 +38,37 @@ npm i --save-dev leerness && npx leerness handoff .
|
|
|
38
38
|
|
|
39
39
|
> npmjs.com의 `npm i leerness`는 라이브러리 import용. CLI 명령(`leerness ...`) 직접 호출은 위 3가지 중 하나 필요.
|
|
40
40
|
|
|
41
|
+
### 🚨 npx 캐시 함정 주의 (1.9.33부터 자동 경고)
|
|
42
|
+
|
|
43
|
+
**`@latest` 없이 `npx leerness init`만 입력하면 PC에 캐시된 옛 버전이 무한히 재사용됩니다.**
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
# ❌ 위험 — 캐시된 옛 버전 실행될 수 있음
|
|
47
|
+
npx leerness init .
|
|
48
|
+
|
|
49
|
+
# ✅ 안전 — 항상 최신 받음
|
|
50
|
+
npx leerness@latest init .
|
|
51
|
+
|
|
52
|
+
# ✅ 캐시가 의심스러우면 비우고 다시
|
|
53
|
+
npx --yes clear-npx-cache
|
|
54
|
+
npx --yes leerness@latest init .
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
**1.9.33부터** `leerness init` 실행 시 npm registry latest와 자동 비교하여, **옛 버전이 실행 중이면 즉시 경고를 출력**합니다:
|
|
58
|
+
|
|
59
|
+
```
|
|
60
|
+
⚠ 옛 버전이 실행 중입니다 — v1.9.21 → v1.9.33 (npm 최신)
|
|
61
|
+
|
|
62
|
+
npm registry latest: v1.9.33
|
|
63
|
+
이 CLI가 실행한 버전: v1.9.21 (npx 캐시 또는 글로벌 설치 stale)
|
|
64
|
+
|
|
65
|
+
해결 — 둘 중 하나 실행 후 다시 시도:
|
|
66
|
+
npx --yes clear-npx-cache && npx leerness@latest init .
|
|
67
|
+
npm i -g leerness@latest → leerness init .
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
경고 끄기: `--no-stale-check` 또는 `LEERNESS_NO_STALE_CHECK=1`.
|
|
71
|
+
|
|
41
72
|
### 🎨 1.9.32 설치 경험
|
|
42
73
|
|
|
43
74
|
`leerness init`을 실행하면 **LEERNESS ASCII 배너 + 빠른 시작 가이드 + sub-agent CLI 설정 prompt**가 자동으로 표시됩니다.
|
|
@@ -462,6 +493,9 @@ leerness skill consolidate
|
|
|
462
493
|
| **`LEERNESS_ENABLE_CODEX`** | **1.9.30 — Codex CLI 활성** (=1) |
|
|
463
494
|
| **`LEERNESS_ENABLE_GEMINI`** | **1.9.30 — Gemini CLI 활성** (=1) |
|
|
464
495
|
| **`LEERNESS_ENABLE_COPILOT`** | **1.9.30 — gh copilot 활성** (=1) |
|
|
496
|
+
| `LEERNESS_NO_BANNER` | 1.9.32 — init 시 ASCII 배너 스킵 (=1) |
|
|
497
|
+
| `LEERNESS_NO_PROMPT` | 1.9.32 — readline 인터랙티브 prompt 강제 비활성 (=1) |
|
|
498
|
+
| `LEERNESS_NO_STALE_CHECK` | **1.9.33 — npx 캐시 옛 버전 경고 끄기** (=1) |
|
|
465
499
|
|
|
466
500
|
---
|
|
467
501
|
|
|
@@ -501,12 +535,13 @@ A. `--all-apps`는 현재 디렉토리 + `_apps/*` (또는 부모의 `_apps/*`)
|
|
|
501
535
|
npm test # = node ./scripts/e2e.js
|
|
502
536
|
```
|
|
503
537
|
|
|
504
|
-
**
|
|
538
|
+
**153/153 시나리오** 통과 (1.9.7~1.9.33 회귀 + 신규 검증).
|
|
505
539
|
|
|
506
540
|
---
|
|
507
541
|
|
|
508
542
|
## 📜 변경 이력 (최근)
|
|
509
543
|
|
|
544
|
+
- **1.9.33** — `_warnIfStale()` — `npx leerness init` 시 옛 버전 자동 경고 + 해결 안내 (clear-npx-cache / @latest).
|
|
510
545
|
- **1.9.32** — ASCII 배너 + `leerness setup-agents` 인터랙티브 설정 + 미설치 CLI 자동 설치 시도. `init` 시 자동 prompt.
|
|
511
546
|
- **1.9.31** — `leerness agents quota` (provider별 사용량/한도 추정 + 대시보드 안내). 멀티 에이전트 분배 신호.
|
|
512
547
|
- **1.9.30** — 외부 AI CLI 오케스트레이션 (claude/codex/gemini/copilot) + 환경변수 활성화 정책 + `leerness agents list/check/dispatch`
|
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.33';
|
|
10
10
|
const MARK = '<!-- leerness:managed -->';
|
|
11
11
|
const README_START = '<!-- leerness:project-readme:start -->';
|
|
12
12
|
const README_END = '<!-- leerness:project-readme:end -->';
|
|
@@ -388,6 +388,10 @@ async function install(root, opts = {}) {
|
|
|
388
388
|
root = absRoot(root); mkdirp(root);
|
|
389
389
|
// 1.9.32: init 시 ASCII 배너 + 빠른 시작 가이드 (migrate는 quiet)
|
|
390
390
|
if (!opts.migration && !has('--no-banner')) _banner({ quickStart: !opts.dry });
|
|
391
|
+
// 1.9.33: npx 캐시로 옛 버전이 실행될 때 경고 (migrate/--no-stale-check 시 스킵)
|
|
392
|
+
if (!opts.migration && !has('--no-stale-check') && !opts.nonInteractive) {
|
|
393
|
+
try { await _warnIfStale(root); } catch {}
|
|
394
|
+
}
|
|
391
395
|
const resolved = await resolveInstallOptions(root, opts);
|
|
392
396
|
const lang = resolved.lang;
|
|
393
397
|
const skills = resolved.skills;
|
|
@@ -2320,6 +2324,54 @@ function _checkAgent(agent, opts = {}) {
|
|
|
2320
2324
|
};
|
|
2321
2325
|
}
|
|
2322
2326
|
|
|
2327
|
+
// 1.9.33: npx 캐시 함정 방지 — install 진입 시 npm latest와 비교, stale이면 경고
|
|
2328
|
+
async function _warnIfStale(root, opts = {}) {
|
|
2329
|
+
if (process.env.LEERNESS_NO_STALE_CHECK === '1') return null;
|
|
2330
|
+
const offline = process.env.LEERNESS_OFFLINE === '1';
|
|
2331
|
+
// 24h 캐시: .harness/cache/update-check.json 재사용 — 캐시 fresh면 OFFLINE이어도 비교는 수행
|
|
2332
|
+
try {
|
|
2333
|
+
let latest = null;
|
|
2334
|
+
const cached = readUpdateCache(root);
|
|
2335
|
+
if (cacheFresh(cached, 24) && cached.nextLeerness) {
|
|
2336
|
+
latest = cached.nextLeerness;
|
|
2337
|
+
} else if (!offline) {
|
|
2338
|
+
// 캐시 없음 + 온라인 → npm view 호출 (timeout 8초 — 네트워크 끊겼어도 init 진행 차단 X)
|
|
2339
|
+
latest = await Promise.race([
|
|
2340
|
+
fetchNpmLatest('leerness'),
|
|
2341
|
+
new Promise(resolve => setTimeout(() => resolve(null), 8000))
|
|
2342
|
+
]);
|
|
2343
|
+
if (latest) {
|
|
2344
|
+
try { writeUpdateCache(root, { nextLeerness: latest, runningCli: VERSION }); } catch {}
|
|
2345
|
+
}
|
|
2346
|
+
}
|
|
2347
|
+
// offline + 캐시 없으면 비교 스킵 (네트워크 차단 환경)
|
|
2348
|
+
if (!latest) return null;
|
|
2349
|
+
if (compareVer(latest, VERSION) > 0) {
|
|
2350
|
+
// 옛 버전이 실행 중. ANSI 노란/빨강.
|
|
2351
|
+
const isTty = process.stdout && process.stdout.isTTY;
|
|
2352
|
+
const C = isTty ? { y: s => `\x1b[33m${s}\x1b[0m`, r: s => `\x1b[31m${s}\x1b[0m`, b: s => `\x1b[1m${s}\x1b[0m`, d: s => `\x1b[2m${s}\x1b[0m` }
|
|
2353
|
+
: { y: s => s, r: s => s, b: s => s, d: s => s };
|
|
2354
|
+
log('');
|
|
2355
|
+
log(C.y(' ⚠ ') + C.b(C.r(`옛 버전이 실행 중입니다 — v${VERSION} → v${latest} (npm 최신)`)));
|
|
2356
|
+
log('');
|
|
2357
|
+
log(C.d(' npm registry latest: ') + C.b(`v${latest}`));
|
|
2358
|
+
log(C.d(' 이 CLI가 실행한 버전: ') + C.b(`v${VERSION}`) + C.d(' (npx 캐시 또는 글로벌 설치 stale)'));
|
|
2359
|
+
log('');
|
|
2360
|
+
log(C.d(' 해결 — 둘 중 하나 실행 후 다시 시도:'));
|
|
2361
|
+
log(' ' + C.b('npx --yes clear-npx-cache && npx leerness@latest init .'));
|
|
2362
|
+
log(' ' + C.b('npm i -g leerness@latest → leerness init .'));
|
|
2363
|
+
log('');
|
|
2364
|
+
log(C.d(' (이 경고는 LEERNESS_NO_STALE_CHECK=1 또는 --no-stale-check로 끌 수 있습니다)'));
|
|
2365
|
+
log('');
|
|
2366
|
+
return { stale: true, current: VERSION, latest };
|
|
2367
|
+
}
|
|
2368
|
+
return { stale: false, current: VERSION, latest };
|
|
2369
|
+
} catch (e) {
|
|
2370
|
+
// 어떤 이유로든 실패해도 init 진행 차단 X
|
|
2371
|
+
return null;
|
|
2372
|
+
}
|
|
2373
|
+
}
|
|
2374
|
+
|
|
2323
2375
|
// 1.9.32: ASCII 배너 — init/version 시 출력
|
|
2324
2376
|
function _banner(opts = {}) {
|
|
2325
2377
|
const v = `v${VERSION}`;
|
|
@@ -4812,7 +4864,7 @@ function viewworkInstall(root) {
|
|
|
4812
4864
|
}
|
|
4813
4865
|
|
|
4814
4866
|
function help() {
|
|
4815
|
-
log(`Leerness v${VERSION}\n\nUsage:\n leerness init [path] [--language auto|ko|en] [--skills recommended|all|a,b]\n leerness migrate [path] [--dry-run] [--force]\n leerness update [path] [--check|--yes|--force|--from <tarball>]\n leerness auto-update install [path]\n leerness status [path]\n leerness verify [path]\n leerness debug [path]\n leerness audit [path]\n leerness check [path]\n leerness scan secrets [path]\n leerness encoding check [path]\n leerness lazy detect [path]\n leerness memory search "query" [--limit 5]\n leerness handoff [path] [--all-apps] [--include p1,p2] [--since 24h|3d] [--compact] [--json] # 1.9.17-22 워크스페이스 (--compact: LLM 시스템 프롬프트용 1줄 요약)\n leerness orchestrate "<목표>" [--agents N] [--model qwen2.5:7b-instruct] [--retry-on-fail K] # 1.9.22 Ollama opt-in (LEERNESS_OLLAMA_BASE_URL 필요)\n leerness llm-bench record --score N --model X [--label L] [--tokens T] # 1.9.22 LLM 벤치 히스토리 누적\n leerness deps <capability> [--run-tests] [--json] # 1.9.24 depends-on 역방향 추적 + 자동 회귀 sweep\n leerness memory search "키" [--include-code] # 1.9.25 소스 코드 본문도 검색 (모순 감지 핵심)\n leerness brainstorm "주제" [--include-code] # 1.9.25 코드 본문 hits 포함\n leerness register-pending "<요청>" [--agent X] [--note Y] # 1.9.25 다중 세션 in-progress 즉시 등록\n leerness optimism-check <T-ID> [--json] # 1.9.26/27 낙관적 표시 감지 (1.9.27: 10 카테고리 + URL/메서드 매핑 + 신뢰도 점수)\n leerness persona list|show <id>|add <id> # 1.9.29 페르소나 카탈로그 (보안/성능/UX/testing/docs 5종 내장)\n leerness review <file> --persona <id1,id2,...> # 1.9.29 도메인 페르소나 리뷰 프롬프트 자동 생성\n leerness agents list|check|quota # 1.9.30/31 외부 AI CLI 가용성 + quota 추정 (claude/codex/gemini/copilot)\n leerness agents dispatch "<task>" --to <id> # 1.9.30 활성 CLI 대상 실행 명령 생성 (실 호출 X, 사용자 실행)\n leerness setup-agents [path] [--yes|--no-setup-agents] # 1.9.32 sub-agent CLI 인터랙티브 설정 (.env + 미설치 자동 설치)\n leerness verify-claim <T-ID> ... [--strict-claims] # 1.9.26 verify-claim에 낙관적 표시 자동 검사 통합\n leerness reuse-map [path] [--all-apps] [--include p1,p2] [--strict-elements] [--json] # 1.9.18 중복/잠재중복/depends-on\n leerness verify-claim <T-ID> [--path .] [--run-tests] [--json] # 1.9.18-20 evidence 자동 검증 (1.9.20: scenes/scripts 등 도메인 폴더 + jest/mocha 파싱)\n leerness verify-code [path] [--build] [--bench] # 1.9.20 --bench: scripts.bench 추가 실행 + evidence 누적\n leerness session close [path]\n leerness viewwork install [path]\n leerness viewwork emit [path] [--action a] [--note n] [--agent x] [--tool t]\n leerness route <task-type>\n leerness self check [path]\n leerness readme sync [path]\n leerness consistency check [path]\n leerness consistency merge-design-guide [path]\n leerness plan show|init|add|drop|progress|sync [args]\n leerness task list|add|update|drop|fix-evidence|relink [args]\n leerness skill list|info <name>\n leerness skill learn <id> --doc <url> --command "..." --capability "..." [--note ...]\n leerness skill use <id> [--note ...]\n leerness skill optimize <id> --before "..." --after "..." [--note ...]\n leerness skill remove <id>\n leerness skill consolidate [--threshold 0.3]\n leerness gate [path] # verify+audit+scan+encoding+lazy
|
|
4867
|
+
log(`Leerness v${VERSION}\n\nUsage:\n leerness init [path] [--language auto|ko|en] [--skills recommended|all|a,b]\n leerness migrate [path] [--dry-run] [--force]\n leerness update [path] [--check|--yes|--force|--from <tarball>]\n leerness auto-update install [path]\n leerness status [path]\n leerness verify [path]\n leerness debug [path]\n leerness audit [path]\n leerness check [path]\n leerness scan secrets [path]\n leerness encoding check [path]\n leerness lazy detect [path]\n leerness memory search "query" [--limit 5]\n leerness handoff [path] [--all-apps] [--include p1,p2] [--since 24h|3d] [--compact] [--json] # 1.9.17-22 워크스페이스 (--compact: LLM 시스템 프롬프트용 1줄 요약)\n leerness orchestrate "<목표>" [--agents N] [--model qwen2.5:7b-instruct] [--retry-on-fail K] # 1.9.22 Ollama opt-in (LEERNESS_OLLAMA_BASE_URL 필요)\n leerness llm-bench record --score N --model X [--label L] [--tokens T] # 1.9.22 LLM 벤치 히스토리 누적\n leerness deps <capability> [--run-tests] [--json] # 1.9.24 depends-on 역방향 추적 + 자동 회귀 sweep\n leerness memory search "키" [--include-code] # 1.9.25 소스 코드 본문도 검색 (모순 감지 핵심)\n leerness brainstorm "주제" [--include-code] # 1.9.25 코드 본문 hits 포함\n leerness register-pending "<요청>" [--agent X] [--note Y] # 1.9.25 다중 세션 in-progress 즉시 등록\n leerness optimism-check <T-ID> [--json] # 1.9.26/27 낙관적 표시 감지 (1.9.27: 10 카테고리 + URL/메서드 매핑 + 신뢰도 점수)\n leerness persona list|show <id>|add <id> # 1.9.29 페르소나 카탈로그 (보안/성능/UX/testing/docs 5종 내장)\n leerness review <file> --persona <id1,id2,...> # 1.9.29 도메인 페르소나 리뷰 프롬프트 자동 생성\n leerness agents list|check|quota # 1.9.30/31 외부 AI CLI 가용성 + quota 추정 (claude/codex/gemini/copilot)\n leerness agents dispatch "<task>" --to <id> # 1.9.30 활성 CLI 대상 실행 명령 생성 (실 호출 X, 사용자 실행)\n leerness setup-agents [path] [--yes|--no-setup-agents] # 1.9.32 sub-agent CLI 인터랙티브 설정 (.env + 미설치 자동 설치)\n leerness init [path] [--no-stale-check] # 1.9.33 npx 캐시 함정 — 옛 버전 자동 경고 (끄려면 --no-stale-check)\n leerness verify-claim <T-ID> ... [--strict-claims] # 1.9.26 verify-claim에 낙관적 표시 자동 검사 통합\n leerness reuse-map [path] [--all-apps] [--include p1,p2] [--strict-elements] [--json] # 1.9.18 중복/잠재중복/depends-on\n leerness verify-claim <T-ID> [--path .] [--run-tests] [--json] # 1.9.18-20 evidence 자동 검증 (1.9.20: scenes/scripts 등 도메인 폴더 + jest/mocha 파싱)\n leerness verify-code [path] [--build] [--bench] # 1.9.20 --bench: scripts.bench 추가 실행 + evidence 누적\n leerness session close [path]\n leerness viewwork install [path]\n leerness viewwork emit [path] [--action a] [--note n] [--agent x] [--tool t]\n leerness route <task-type>\n leerness self check [path]\n leerness readme sync [path]\n leerness consistency check [path]\n leerness consistency merge-design-guide [path]\n leerness plan show|init|add|drop|progress|sync [args]\n leerness task list|add|update|drop|fix-evidence|relink [args]\n leerness skill list|info <name>\n leerness skill learn <id> --doc <url> --command "..." --capability "..." [--note ...]\n leerness skill use <id> [--note ...]\n leerness skill optimize <id> --before "..." --after "..." [--note ...]\n leerness skill remove <id>\n leerness skill consolidate [--threshold 0.3]\n leerness gate [path] # verify+audit+scan+encoding+lazy
|
|
4816
4868
|
leerness retro [path] [--days 7] [--all-apps] [--include p1,p2] [--json] # 회고 (1.9.13~1.9.16)
|
|
4817
4869
|
leerness insights [path] [--all-apps] [--include p1,p2] [--json] # 누적 통계 (1.9.13~1.9.16)
|
|
4818
4870
|
leerness brainstorm "<주제>" [--all-apps] [--include p1,p2] [--json] # 브레인스토밍 (1.9.13~1.9.16)
|
package/package.json
CHANGED
package/scripts/e2e.js
CHANGED
|
@@ -931,6 +931,44 @@ total++;
|
|
|
931
931
|
if (!ok) { failed++; console.log(after); }
|
|
932
932
|
}
|
|
933
933
|
|
|
934
|
+
// 1.9.33 회귀: npx 캐시 함정 — stale 버전 실행 시 경고
|
|
935
|
+
total++;
|
|
936
|
+
{
|
|
937
|
+
// 캐시에 미래 버전을 심어 stale 시뮬레이션 → 경고 출력 + init은 계속 진행
|
|
938
|
+
const tmpC = fs.mkdtempSync(path.join(os.tmpdir(), 'leerness-stale-'));
|
|
939
|
+
cp.spawnSync(process.execPath, [CLI, 'init', tmpC, '--yes', '--language', 'ko', '--skills', 'recommended', '--no-stale-check'], { stdio: 'ignore', timeout: 30000 });
|
|
940
|
+
const cacheDir = path.join(tmpC, '.harness', 'cache');
|
|
941
|
+
fs.mkdirSync(cacheDir, { recursive: true });
|
|
942
|
+
fs.writeFileSync(path.join(cacheDir, 'update-check.json'), JSON.stringify({ at: Date.now(), nextLeerness: '99.99.99', runningCli: require('../package.json').version }), 'utf8');
|
|
943
|
+
const r = cp.spawnSync(process.execPath, [CLI, 'init', tmpC, '--yes', '--no-banner', '--language', 'ko', '--skills', 'recommended'], { encoding: 'utf8', timeout: 30000 });
|
|
944
|
+
const ok = r.status === 0
|
|
945
|
+
&& /옛 버전이 실행 중입니다/.test(r.stdout)
|
|
946
|
+
&& /v99\.99\.99/.test(r.stdout)
|
|
947
|
+
&& /clear-npx-cache/.test(r.stdout)
|
|
948
|
+
&& /Leerness v/.test(r.stdout); // init도 계속 진행
|
|
949
|
+
console.log(ok ? '✓ B(1.9.33) npx stale 경고: 미래 latest 캐시 시 경고 + init 계속' : `✗ stale 경고 실패`);
|
|
950
|
+
if (!ok) { failed++; console.log(r.stdout.slice(0, 800)); }
|
|
951
|
+
}
|
|
952
|
+
|
|
953
|
+
total++;
|
|
954
|
+
{
|
|
955
|
+
// --no-stale-check / LEERNESS_NO_STALE_CHECK=1: 경고 스킵
|
|
956
|
+
const tmpC = fs.mkdtempSync(path.join(os.tmpdir(), 'leerness-stale2-'));
|
|
957
|
+
cp.spawnSync(process.execPath, [CLI, 'init', tmpC, '--yes', '--language', 'ko', '--skills', 'recommended', '--no-stale-check'], { stdio: 'ignore', timeout: 30000 });
|
|
958
|
+
const cacheDir = path.join(tmpC, '.harness', 'cache');
|
|
959
|
+
fs.mkdirSync(cacheDir, { recursive: true });
|
|
960
|
+
fs.writeFileSync(path.join(cacheDir, 'update-check.json'), JSON.stringify({ at: Date.now(), nextLeerness: '99.99.99' }), 'utf8');
|
|
961
|
+
// --no-stale-check
|
|
962
|
+
const r1 = cp.spawnSync(process.execPath, [CLI, 'init', tmpC, '--yes', '--no-banner', '--no-stale-check', '--language', 'ko', '--skills', 'recommended'], { encoding: 'utf8', timeout: 30000 });
|
|
963
|
+
// env flag
|
|
964
|
+
const r2 = cp.spawnSync(process.execPath, [CLI, 'init', tmpC, '--yes', '--no-banner', '--language', 'ko', '--skills', 'recommended'], { encoding: 'utf8', timeout: 30000, env: { ...process.env, LEERNESS_NO_STALE_CHECK: '1' } });
|
|
965
|
+
const ok = r1.status === 0 && r2.status === 0
|
|
966
|
+
&& !/옛 버전이 실행 중입니다/.test(r1.stdout)
|
|
967
|
+
&& !/옛 버전이 실행 중입니다/.test(r2.stdout);
|
|
968
|
+
console.log(ok ? '✓ B(1.9.33) stale 스킵: --no-stale-check + LEERNESS_NO_STALE_CHECK=1' : `✗ stale skip 실패`);
|
|
969
|
+
if (!ok) { failed++; console.log(r1.stdout.slice(0, 400)); }
|
|
970
|
+
}
|
|
971
|
+
|
|
934
972
|
// 1.9.22 회귀: handoff --compact + orchestrate opt-in 정책 + llm-bench record
|
|
935
973
|
total++;
|
|
936
974
|
{
|