leerness 1.23.0 → 1.25.0
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 +97 -0
- package/README.md +4 -4
- package/bin/leerness.js +251 -56
- package/lib/session-close.js +2 -2
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,102 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.25.0 — 2026-06-15 — 🛡️ [안정화/Stable] 마감 본문 정직성 + lens 플래그십 영어화 안정 minor
|
|
4
|
+
|
|
5
|
+
**🛡️ 안정화(Stable) minor — 자가 검증으로 잡은 정직성 수정 + 품질 렌즈 영어화를 npm 공개.** 직전 minor(1.24.0) 이후 누적된 패치 2건(1.24.1 + 1.24.2)을 검증·통합해 배포. R-0011 정책의 16번째 stable minor. 한국어 우선 기본은 그대로.
|
|
6
|
+
|
|
7
|
+
### 이번 minor 통합 (1.24.1~1.24.2)
|
|
8
|
+
- **🔎 session close 보고 본문 정직성 수정 (1.24.1)**: 게시된 모든 영어 표면을 `--language en` 으로 실행해 한글 누출을 자동 스캔(맹신 X — 내 'CLOSED' 주장 재실증)한 결과, 1.23.0 "session close 완전 영어" 가 과장임을 발견 → 보고 본문 잔여 영어화(`- 없음`→`- none`, `완료/결정 누적`→`done/decisions accumulated`, roadmap `자동 갱신`→`auto-updated`).
|
|
9
|
+
- **🌐 lens 품질 렌즈 플래그십 영어화 (1.24.2)**: 분야별 자기질문 품질 렌즈 5 도메인(code/design/docs/test/security)에 영어 병렬 카탈로그 추가 + `--language en` 렌더. 영어권 사용자도 완료 선언 전 자가 점검 + 분야간 인과를 활용.
|
|
10
|
+
- **한국어 우선 기본 보존**: 영어는 명시 opt-in. 한국어 원문/렌즈 질문은 한 글자도 안 바뀜(e2e 무회귀).
|
|
11
|
+
|
|
12
|
+
### 잔여 (UR-0010 Phase 9+, 백로그)
|
|
13
|
+
- 진단/정보 명령 본문(health/capabilities/commands/doctor/drift/install-safety/constraints) + 메모리 CRUD 빈상태 메시지 + handoff 본문 + init starter 데이터 — en-leak 스캔 우선순위순 단계적 확대.
|
|
14
|
+
|
|
15
|
+
### 검증 (회귀 0)
|
|
16
|
+
- **selftest 244/244** (정직성 + lens 영어/한국어 보존 소스가드 포함) · 행위(en-leak 스캔: session close 본문·lens en 한글 0 / ko 보존) · **E2E 365/365**.
|
|
17
|
+
- minor(1.25.0) — npm 배포(R-0011 stable) + annotated tag(Stable) + GitHub release(latest) + 게시본 클린룸 재실증.
|
|
18
|
+
|
|
19
|
+
## 1.24.2 — 2026-06-15 — CLI 영어화 Phase 8: lens(품질 렌즈 플래그십) 영어화 (UR-0010)
|
|
20
|
+
|
|
21
|
+
**🌐 품질 렌즈를 영어로.** 남은 한국어 표면을 en-leak 스캔으로 매핑한 뒤, 가장 가치 높은 플래그십 — **분야별 자기질문 품질 렌즈(`leerness lens`)** — 를 영어화. 영어권 사용자도 "완료 선언 전 자가 점검" + 분야간 인과관계를 그대로 활용할 수 있습니다.
|
|
22
|
+
|
|
23
|
+
### 변경 (UR-0010 Phase 8)
|
|
24
|
+
- **lens 영어 병렬 카탈로그**: `LENS_CATALOG` 5 도메인(code/design/docs/test/security)에 `titleEn`/`personaEn`/`questionsEn`/`affectsNoteEn` 추가. 한국어 원문(`questions`/`persona` 등)은 **한 글자도 안 바꿈** — selftest `userVerbatim` 가드 + e2e(ko) 안전.
|
|
25
|
+
- **lensCmd 영어 렌더**: `--language en` 시 헤더/부제/페르소나/질문/↔인과/푸터/unknown 에러 모두 영어. 프로젝트 커스텀 렌즈(.harness/quality-lenses.json)는 영어 필드가 없으면 작성된 텍스트로 graceful fallback, builtin 도메인에 추가한 커스텀 질문은 `questionsEn` 개수 기준으로 분리해 영어 렌더에 append.
|
|
26
|
+
- **한국어 기본 유지**: 영어는 명시 opt-in. 플래그 없으면 한국어 그대로(e2e 무회귀).
|
|
27
|
+
|
|
28
|
+
### 잔여 (UR-0010 Phase 9+, 백로그)
|
|
29
|
+
- 진단/정보 명령 본문(health/capabilities/commands/doctor/drift check/install-safety/constraints) + 메모리 CRUD 빈상태 메시지 + handoff 본문 + init starter 데이터 — en-leak 스캔 우선순위순 단계적 확대.
|
|
30
|
+
|
|
31
|
+
### 검증 (회귀 0)
|
|
32
|
+
- **selftest 243→244** (lens 영어 병렬필드 + ko verbatim + 렌더 영어 분기 소스가드) · 행위(en-leak 재스캔: `lens --language en` 한글 0 / ko 29줄 보존 / unknown 에러 en·ko) · **E2E 365/365**.
|
|
33
|
+
- patch(1.24.2) — npm 미배포(R-0011, GitHub/CHANGELOG 누적).
|
|
34
|
+
|
|
35
|
+
## 1.24.1 — 2026-06-15 — 정직성 수정: session close 보고 본문 잔여 한국어 영어화 (UR-0010)
|
|
36
|
+
|
|
37
|
+
**🔎 자가 검증으로 발견한 과장 주장 교정.** 게시된 모든 영어 표면을 `--language en` 으로 직접 실행해 한국어(가-힣) 누출을 스캔(맹신 X — 내 'CLOSED' 주장 재실증)한 결과: help/status/group help 는 깨끗했지만, **session close 보고 본문**은 1.23.0 에서 "완전 영어"로 배포했음에도 일부 한국어가 남아 있었습니다. 그 잔여를 영어화.
|
|
38
|
+
|
|
39
|
+
### 변경 (UR-0010)
|
|
40
|
+
- **session close 보고 본문 영어화**: 빈 섹션 표시 `- 없음`→`- none`(rowsToList, 헤더는 이미 영어라 정합↑), 진행 요약 한 줄 `완료 N/M · 결정 N건 누적`→`done N/M · decisions N accumulated`(`_retroOneLine` 에 선택적 lang), roadmap 자동 갱신 로그 `자동 갱신`→`auto-updated`(`_autoRoadmap`, `_uiLang(root)` 기반).
|
|
41
|
+
- **한국어 기본 불변**: 모든 변경은 en 분기에만. ko 는 한 글자도 안 바뀜(e2e 무회귀). `_retroOneLine` 의 기존 호출부(retro 명령)는 lang 미전달 → ko 유지.
|
|
42
|
+
- **검증 방법 공개**: en-leak 스캔(Node `[가-힣]` 탐지 — grep `\x{}` 빌드 한계 우회)으로 재실증. 남은 2줄은 seeded T-0001 + task-add 기본 next-action 값(데이터, Phase 8).
|
|
43
|
+
|
|
44
|
+
### 잔여 (UR-0010 Phase 8+, 백로그)
|
|
45
|
+
- handoff 본문 + 메모리 CRUD/진단 명령 본문(task/decision/audit/gate/scan 사람용 메시지) + init starter 콘텐츠/task-add 기본값 — 단계적 확대.
|
|
46
|
+
|
|
47
|
+
### 검증 (회귀 0)
|
|
48
|
+
- **selftest 242→243** (보고 본문 영어/한국어 보존 소스가드) · 행위(en fresh: `- none / done 0/1 · decisions 0 accumulated / roadmap.html auto-updated`, ko fresh: `- 없음 / 완료 0/1 · 결정 0건 누적 / 자동 갱신`) · **E2E 365/365**.
|
|
49
|
+
- patch(1.24.1) — npm 미배포(R-0011, GitHub/CHANGELOG 누적).
|
|
50
|
+
|
|
51
|
+
## 1.24.0 — 2026-06-15 — 🛡️ [안정화/Stable] help 표면 전체 영어화 안정 minor
|
|
52
|
+
|
|
53
|
+
**🛡️ 안정화(Stable) minor — `leerness --help` 와 모든 도움말 표면을 영어로 공개.** 직전 minor(1.23.0) 이후 누적된 패치 2건(1.23.1 Phase 6 + 1.23.2 Phase 7)을 검증·통합해 npm 배포. R-0011 정책의 15번째 stable minor. 이제 영어 사용자가 **메인 도움말 → 명령군 그룹 도움말 → 사용법 힌트**까지 막힘없이 읽을 수 있습니다. 한국어 우선 기본은 그대로.
|
|
54
|
+
|
|
55
|
+
### 이번 minor 통합 (1.23.1~1.23.2)
|
|
56
|
+
- **🌐 메인 help 영어 큐레이트판 (Phase 6)**: `--language en` 시 8개 카테고리(Setup·Diagnostics·Verification·Security·Handoff·Memory·Skills·Agents·Reuse·Release·More)로 정리된 영어 도움말. 레거시 버전태그 군더더기를 빼 영어 사용자가 읽기 쉬움. status 잔여(경로 없음/healthyMeaning) + subcommand_required 에러도 영어화.
|
|
57
|
+
- **🌐 그룹 help + 사용법 힌트 영어화 (Phase 7)**: requests/constraints/wakeup-interval/idempotency/intent 의 bare-command 도움말 + `_GROUP_USAGE` 자리표시자(`<text>`/`<trigger>`/`<key>`/`<name>`, 병렬 영어맵).
|
|
58
|
+
- **한국어 우선 기본 보존**: 영어는 명시 opt-in(`--language en`/`LEERNESS_LANG=en`/en init 프로젝트). 플래그 없으면 한국어 — 한국어 help/맵은 한 글자도 안 바뀜(e2e 무회귀로 검증).
|
|
59
|
+
|
|
60
|
+
### 잔여 (UR-0010 Phase 8+, 백로그)
|
|
61
|
+
- 메모리 CRUD/진단 명령 본문 출력(task/decision/audit/gate/scan 등 사람용 메시지) + session-handoff.md 본문 — 단계적 확대.
|
|
62
|
+
|
|
63
|
+
### 검증 (회귀 0)
|
|
64
|
+
- **selftest 242/242** (Phase 6·7 영어/한국어 보존 소스가드 포함) · 행위(en: `SETUP & UPDATE / 5 group headers / <key>`, ko 기본: `Usage: / 한국어 그룹 헤더 / <키>`) · **E2E 365/365**.
|
|
65
|
+
- minor(1.24.0) — npm 배포(R-0011 stable) + annotated tag(Stable) + GitHub release(latest) + 게시본 클린룸 재실증.
|
|
66
|
+
|
|
67
|
+
## 1.23.2 — 2026-06-15 — CLI 영어화 Phase 7: group help 5종 + _GROUP_USAGE 자리표시자 영어화 (UR-0010)
|
|
68
|
+
|
|
69
|
+
**🌐 도움말 표면 패밀리 완성.** Phase 6(메인 `--help`)에 이어, 명령군을 하위명령 없이 부를 때 나오는 **그룹 도움말**과 **사용법 힌트의 자리표시자**까지 영어화 — 메인 help + group help + usage hint 가 모두 언어 선택을 따른다.
|
|
70
|
+
|
|
71
|
+
### 변경 (UR-0010 Phase 7)
|
|
72
|
+
- **group help 5종 영어화**: `requests` / `constraints` / `wakeup-interval` / `idempotency` / `intent` 를 하위명령 없이(또는 `help`) 부를 때의 도움말을 `_t(ko,en)` 분기.
|
|
73
|
+
- **_GROUP_USAGE 자리표시자 영어화**: `<텍스트>`→`<text>`, `<트리거>`→`<trigger>`, `<키>`→`<key>`, `<이름>`→`<name>` — `_GROUP_USAGE_EN` 병렬맵으로(한국어 맵은 한 글자도 안 바꿔 e2e 안전), subcommand_required 에러가 언어별 정확한 사용법 표시.
|
|
74
|
+
- **한국어 기본 유지**: 영어는 명시 opt-in. 플래그 없으면 기존 한국어 그대로(e2e 무회귀).
|
|
75
|
+
|
|
76
|
+
### 잔여 (UR-0010 Phase 8+, 백로그)
|
|
77
|
+
- 메모리 CRUD/진단 명령 본문 출력(task/decision/audit/gate/scan 등 사람용 메시지) + session-handoff.md 본문 — 단계적 확대.
|
|
78
|
+
|
|
79
|
+
### 검증 (회귀 0)
|
|
80
|
+
- **selftest 241→242** (group help 5종 영어+한국어 보존, _GROUP_USAGE_EN 존재 + ko 맵 불변 소스가드) · 행위(en: 5종 영어 헤더 + `<key>`/`<text>`, ko 기본: 5종 한국어 헤더 + `<키>`/`<텍스트>`) · **E2E 365/365**.
|
|
81
|
+
- patch(1.23.2) — npm 미배포(R-0011, GitHub/CHANGELOG 누적).
|
|
82
|
+
|
|
83
|
+
## 1.23.1 — 2026-06-15 — CLI 영어화 Phase 6: help(영어 큐레이트판) + status/subcommand 에러 영어화 (UR-0010)
|
|
84
|
+
|
|
85
|
+
**🌐 `leerness --help` 와 흔한 에러를 영어로.** 영어 사용자가 가장 먼저 보는 도움말을 — 레거시 버전태그를 줄별로 번역하는 대신 — **카테고리별로 정리한 별도 영어 도움말**로 제공. 한국어 도움말은 그대로 둬서 한국어 기본 경로는 한 글자도 안 바뀜.
|
|
86
|
+
|
|
87
|
+
### 변경 (UR-0010 Phase 6)
|
|
88
|
+
- **help 영어 큐레이트판 (`_helpEn`)**: `--language en`/`LEERNESS_LANG=en` 시 8개 카테고리(Setup·Diagnostics·Verification·Security·Handoff·Memory·Skills·Agents·Reuse·Release·More)로 정리된 영어 도움말. 전체 전수 목록은 `leerness commands` 안내(드리프트 방지).
|
|
89
|
+
- **status 잔여 영어화**: 경로 없음 에러(`path not found`), `--json` 의 `healthyMeaning`(`install-file presence only …`).
|
|
90
|
+
- **subcommand_required 에러 영어화**: 명령군(rule/skill/feature/memory)을 하위명령 없이 부를 때의 `subcommand required — usage: …`.
|
|
91
|
+
- **한국어 기본 유지**: 영어는 명시 opt-in. 플래그 없으면 기존 한국어 도움말/에러 그대로(e2e 무회귀).
|
|
92
|
+
|
|
93
|
+
### 잔여 (UR-0010 Phase 7+, 백로그)
|
|
94
|
+
- `_GROUP_USAGE` 내부 자리표시자(`<텍스트>`/`<트리거>`) + 명령별 하위 help 블록(group help) + session-handoff.md 본문 — 단계적 확대.
|
|
95
|
+
|
|
96
|
+
### 검증 (회귀 0)
|
|
97
|
+
- **selftest 240→241** (help 영어판 존재+핵심 카테고리 포함, ko help 분기 보존, status/subcommand 영어/한국어 소스가드) · 행위(en: `SETUP & UPDATE / path not found / subcommand required`, ko 기본: `Usage: / 경로 없음 / 하위명령 필요`) · **E2E 365/365**.
|
|
98
|
+
- patch(1.23.1) — npm 미배포(R-0011, GitHub/CHANGELOG 누적).
|
|
99
|
+
|
|
3
100
|
## 1.23.0 — 2026-06-15 — 🛡️ [안정화/Stable] session close 영어 완전화 안정 minor
|
|
4
101
|
|
|
5
102
|
**🛡️ 안정화(Stable) minor — 세션 마감 화면 전체를 영어로 공개.** 직전 minor(1.22.0) 이후 누적된 패치 2건(1.22.1 Phase 4 + 1.22.2 Phase 5)을 검증·통합해 npm 배포. R-0011 정책의 14번째 stable minor. 이로써 **핵심 세션 라이프사이클 — 설치(init) → 시작(handoff) → 검증(verify-claim) → 마감(session close) — 전체가 영어 opt-in 으로 일관**됩니다. 한국어 우선 기본은 그대로.
|
package/README.md
CHANGED
|
@@ -104,7 +104,7 @@ MIT
|
|
|
104
104
|
<!-- leerness:project-readme:start -->
|
|
105
105
|
## Leerness Project Harness
|
|
106
106
|
|
|
107
|
-
이 프로젝트는 Leerness v1.
|
|
107
|
+
이 프로젝트는 Leerness v1.25.0 하네스를 사용합니다. AI 에이전트는 작업 전 `leerness handoff`로 컨텍스트를 적재하고, 작업 후 `leerness check`/`leerness audit`/`leerness session close`를 수행해야 합니다.
|
|
108
108
|
|
|
109
109
|
### 정체성 — AI 에이전트 운영 레이어 (UR-0030)
|
|
110
110
|
|
|
@@ -158,7 +158,7 @@ leerness memory restore decision <date|title>
|
|
|
158
158
|
|
|
159
159
|
### MCP server (외부 AI 통합)
|
|
160
160
|
|
|
161
|
-
Leerness v1.
|
|
161
|
+
Leerness v1.25.0는 stdio JSON-RPC MCP server를 내장합니다 — Claude Code · Cursor · Codex CLI 등 외부 AI에 **85개 도구**를 노출:
|
|
162
162
|
|
|
163
163
|
```jsonc
|
|
164
164
|
// 카테고리별
|
|
@@ -179,7 +179,7 @@ Leerness v1.23.0는 stdio JSON-RPC MCP server를 내장합니다 — Claude Code
|
|
|
179
179
|
`<<autonomous-loop-dynamic>>` 신호만 보내면 AI가:
|
|
180
180
|
1) 다음 라운드 후보 선정 → 2) 코드 변경 → 3) stress-v* 신규 작성 + 누적 회귀 → 4) e2e 219/219 → 5) npm pack + git tag + GitHub release → 6) main 자동 push (1.9.140+) → 7) session close → 8) 다음 라운드 예약.
|
|
181
181
|
|
|
182
|
-
현재 누적: **70 라운드 (1.9.40 → 1.
|
|
182
|
+
현재 누적: **70 라운드 (1.9.40 → 1.25.0)** · 매 라운드 GitHub release/태그 생성 · _reports/는 비공개 보존.
|
|
183
183
|
|
|
184
184
|
### 성능 가이드 (1.9.140 측정)
|
|
185
185
|
|
|
@@ -217,6 +217,6 @@ leerness release pack --close --auto-main-push
|
|
|
217
217
|
- `.harness/session-handoff.md`: 다음 세션 인수인계 (자동 작성)
|
|
218
218
|
- `.harness/lessons.md` / `decisions.md` / `rules.md`: 영구 메모리 (5 surface)
|
|
219
219
|
|
|
220
|
-
Last synced by Leerness v1.
|
|
220
|
+
Last synced by Leerness v1.25.0: 2026-06-15
|
|
221
221
|
<!-- leerness:project-readme:end -->
|
|
222
222
|
|
package/bin/leerness.js
CHANGED
|
@@ -32,7 +32,7 @@ const { _evidenceQuality, _parseEvidenceStats, _shellGuardAnalyze, _claimFileInG
|
|
|
32
32
|
// 1.9.295 (UR-0025 4단계): 정적 데이터 카탈로그 모듈 분리 (비파괴, require-based).
|
|
33
33
|
const { CAPABILITY_SURFACE, POWERFUL_COMMANDS, ADAPTERS, REUSE_CATEGORIES, REUSE_CHECKLIST, _DEFAULT_PLATFORM_CONSTRAINTS, _DEFAULT_DOMAIN_CATALOG, _TOOL_CATALOG, _LSP_LANG_PATTERNS, OPTIMISM_PATTERNS, BUILT_IN_PERSONAS, STRINGS, BUILTIN_CATALOG, ROADMAP_STATUS_LABEL, ROADMAP_STATUS_COLOR, SECRET_PATTERNS, MERGE_OVERWRITE_FILES, MINIMAL_SKIP_KEYS, REQUIRED_WORKSPACE_FILES, KEYWORD_STOPWORDS, SKILL_CATALOG_PRESETS } = require('../lib/catalogs'); // 1.9.344/368/369 (UR-0025): catalog 분리 · 1.11.4 (UR-0007): _TOOL_CATALOG
|
|
34
34
|
|
|
35
|
-
const VERSION = '1.
|
|
35
|
+
const VERSION = '1.25.0';
|
|
36
36
|
|
|
37
37
|
// 1.9.290 (UR-0037, Codex gpt-5.5 #4 수렴): CLI 전용 부작용은 require 시 실행하지 않는다.
|
|
38
38
|
// 이전: warning listener 제거 / NODE_OPTIONS 변경 / chcp IIFE 가 top-level 즉시 실행 → require('harness') 시 호스트 프로세스 오염.
|
|
@@ -3764,6 +3764,44 @@ function _selfTestCases() {
|
|
|
3764
3764
|
const noShadow = !sc.includes('.map(([t, n]) =>'); // t 헬퍼 셰도잉 제거 확인
|
|
3765
3765
|
return en && koPreserved && noShadow;
|
|
3766
3766
|
} },
|
|
3767
|
+
{ name: 'CLI 영어화 Phase 6 (1.23.1, UR-0010): help 영어 큐레이트판 + status/subcommand 영어/한국어 보존 (소스 가드)', run: () => {
|
|
3768
|
+
const bin = read(__filename);
|
|
3769
|
+
// en help 가 존재하고 핵심 명령군을 포함 + ko help 분기 보존
|
|
3770
|
+
const enHelp = bin.includes('function _helpEn()') && bin.includes("if (_uiLang(arg('--path', process.cwd())) === 'en') { _helpEn(); return; }");
|
|
3771
|
+
const enCovers = bin.includes('SETUP & UPDATE') && bin.includes('VERIFICATION (evidence-gated') && bin.includes('Full, exhaustive command list');
|
|
3772
|
+
const koPreserved = bin.includes('Leerness v${VERSION}\\n\\nUsage:'); // 한국어 help 원문 유지
|
|
3773
|
+
const statusEn = bin.includes('path not found: ${root}') && bin.includes('install-file presence only');
|
|
3774
|
+
const subEn = bin.includes('subcommand required — usage: leerness');
|
|
3775
|
+
return enHelp && enCovers && koPreserved && statusEn && subEn;
|
|
3776
|
+
} },
|
|
3777
|
+
{ name: 'CLI 영어화 Phase 7 (1.23.2, UR-0010): group help 5종 + _GROUP_USAGE_EN 영어/한국어 보존 (소스 가드)', run: () => {
|
|
3778
|
+
const bin = read(__filename);
|
|
3779
|
+
const en = bin.includes('track missing user requests') && bin.includes('pre-check platform/API constraints') && bin.includes('adaptive wakeup interval') && bin.includes('detect idempotency violations') && bin.includes('infer user intent');
|
|
3780
|
+
const koPreserved = bin.includes('사용자 요청 누락 확인 절차') && bin.includes('플랫폼/API 제약 사전 체크') && bin.includes('멱등성 위반 탐지'); // ko 원문 _t ko 인자로 보존(e2e ko 무회귀)
|
|
3781
|
+
const groupUsageEn = bin.includes('const _GROUP_USAGE_EN = {') && bin.includes('rule add "<text>" --trigger <trigger>') && bin.includes('${_GROUP_USAGE_EN[cmd]}');
|
|
3782
|
+
const koUsagePreserved = bin.includes('rule add "<텍스트>" --trigger <트리거>'); // ko 맵 불변
|
|
3783
|
+
return en && koPreserved && groupUsageEn && koUsagePreserved;
|
|
3784
|
+
} },
|
|
3785
|
+
{ name: '영어화 정직성 (1.24.1, UR-0010): session close 보고 본문(없음/retro/roadmap) 영어/한국어 보존 (소스 가드)', run: () => {
|
|
3786
|
+
const bin = read(__filename);
|
|
3787
|
+
const sc = read(path.join(path.dirname(__filename), '..', 'lib', 'session-close.js'));
|
|
3788
|
+
const rowsEn = sc.includes("t('- 없음', '- none')") && sc.includes('_retroOneLine(agg, uiLang)');
|
|
3789
|
+
const retroEn = bin.includes('function _retroOneLine(agg, lang)') && bin.includes('`done ${done}/${total}') && bin.includes('decisions ${agg.decisionBlocks} accumulated');
|
|
3790
|
+
const roadmapEn = bin.includes('roadmap.html auto-updated (${trigger})');
|
|
3791
|
+
const koPreserved = bin.includes('완료 ${done}/${total}') && bin.includes('roadmap.html 자동 갱신 (${trigger})') && sc.includes("t('- 없음', '- none')"); // ko 인자 보존
|
|
3792
|
+
return rowsEn && retroEn && roadmapEn && koPreserved;
|
|
3793
|
+
} },
|
|
3794
|
+
{ name: 'CLI 영어화 Phase 8 (1.24.2, UR-0010): lens 영어 병렬필드 + 렌더 영어/한국어 보존 (소스 가드)', run: () => {
|
|
3795
|
+
// 카탈로그 영어 병렬필드 + ko verbatim 동시 보존 + 렌더 영어 분기
|
|
3796
|
+
const enFields = LENS_CATALOG.code.questionsEn && LENS_CATALOG.code.questionsEn.length === LENS_CATALOG.code.questions.length
|
|
3797
|
+
&& LENS_CATALOG.code.questionsEn.some(q => q.includes('senior engineer') && q.includes('complex'))
|
|
3798
|
+
&& LENS_CATALOG.design.personaEn.includes('senior designer') && LENS_CATALOG.docs.questionsEn.some(q => q.includes('30 seconds'));
|
|
3799
|
+
const koVerbatim = LENS_CATALOG.code.questions.some(q => q.includes('선임 개발자') && q.includes('복잡'))
|
|
3800
|
+
&& LENS_CATALOG.docs.questions.some(q => q.includes('30초')); // ko 원문 유지(e2e/userVerbatim)
|
|
3801
|
+
const bin = read(__filename);
|
|
3802
|
+
const renderEn = bin.includes('quality self-question lenses (v${VERSION})') && bin.includes("t('페르소나', 'persona')");
|
|
3803
|
+
return enFields && koVerbatim && renderEn;
|
|
3804
|
+
} },
|
|
3767
3805
|
{ name: 'VERSION 형식 (x.y.z)', run: () => /^\d+\.\d+\.\d+$/.test(VERSION) }
|
|
3768
3806
|
];
|
|
3769
3807
|
}
|
|
@@ -4295,51 +4333,89 @@ function pulseCmd(root) {
|
|
|
4295
4333
|
// 1.18.3 (UR-0003 사용자 명시): 분야별 자기질문 품질 렌즈 — AI 가 완료 선언 전 스스로 답해보는 질문 + 분야간 인과관계.
|
|
4296
4334
|
// "선임 개발자가 내 코드를 보고 복잡하다고 느끼지 않을까?" / "선임 디자이너와 일반 사용자가 봤을 때 이쁘고 직관적인가?" (사용자 원문).
|
|
4297
4335
|
// 질문에 "그렇다(통과)"라고 답할 수 없으면 아직 완료가 아님. affects = 이 분야를 바꿨을 때 다시 물어야 할 분야(인과관계).
|
|
4336
|
+
// 1.24.2 (UR-0010 Phase 8): 각 도메인에 영어 병렬 필드(titleEn/personaEn/questionsEn/affectsNoteEn) 추가.
|
|
4337
|
+
// 한국어(title/persona/questions/affectsNote)는 verbatim 유지 — selftest userVerbatim 가드 + e2e(ko) 무회귀.
|
|
4338
|
+
// questionsEn 개수는 builtin questions 와 동일하게 유지(렌더가 커스텀 추가질문을 length 기준으로 분리·append).
|
|
4298
4339
|
const LENS_CATALOG = {
|
|
4299
4340
|
code: {
|
|
4300
4341
|
title: '코드', persona: '선임 개발자',
|
|
4342
|
+
titleEn: 'code quality', personaEn: 'senior engineer',
|
|
4301
4343
|
questions: [
|
|
4302
4344
|
'선임 개발자가 이 코드를 보고 "복잡하다"고 느끼지 않을까? — 가볍고 단순해야 함',
|
|
4303
4345
|
'더 단순한 방법이 있는데 추상화/패턴/옵션을 추가하고 있지 않은가?',
|
|
4304
4346
|
'처음 보는 사람이 5분 안에 이 변경을 이해할 수 있는가?'
|
|
4305
4347
|
],
|
|
4306
|
-
|
|
4348
|
+
questionsEn: [
|
|
4349
|
+
'Would a senior engineer call this code "complex"? — it should be light and simple',
|
|
4350
|
+
'Are you adding abstraction/patterns/options when a simpler way exists?',
|
|
4351
|
+
'Can a newcomer understand this change in 5 minutes?'
|
|
4352
|
+
],
|
|
4353
|
+
affects: ['test', 'docs', 'design'], affectsNote: 'UI 를 만지는 코드 변경이면 design 질문 재확인 필수',
|
|
4354
|
+
affectsNoteEn: 'if the change touches UI, re-check the design questions'
|
|
4307
4355
|
},
|
|
4308
4356
|
design: {
|
|
4309
4357
|
title: '디자인/UX', persona: '선임 디자이너 + 일반 사용자',
|
|
4358
|
+
titleEn: 'design / UX', personaEn: 'senior designer + everyday user',
|
|
4310
4359
|
questions: [
|
|
4311
4360
|
'선임 디자이너가 봤을 때 이쁘고 일관적인가?',
|
|
4312
4361
|
'일반 사용자가 처음 봤을 때 편하고 직관적이며 헷갈리지 않는가?',
|
|
4313
4362
|
'꾸미기 위해 복잡해지고 있지 않은가? — 단순함이 곧 직관'
|
|
4314
4363
|
],
|
|
4315
|
-
|
|
4364
|
+
questionsEn: [
|
|
4365
|
+
'Would a senior designer find it pretty and consistent?',
|
|
4366
|
+
'Is it comfortable, intuitive, and unconfusing for a first-time everyday user?',
|
|
4367
|
+
'Are you adding complexity just to decorate? — simplicity is intuition'
|
|
4368
|
+
],
|
|
4369
|
+
affects: ['code', 'docs'], affectsNote: '디자인 단순화는 보통 코드도 단순하게 만든다 (역도 성립)',
|
|
4370
|
+
affectsNoteEn: 'simplifying design usually simplifies the code too (and vice versa)'
|
|
4316
4371
|
},
|
|
4317
4372
|
docs: {
|
|
4318
4373
|
title: '문서/README', persona: '처음 온 사용자 (비개발자 포함)',
|
|
4374
|
+
titleEn: 'docs / README', personaEn: 'first-time user (incl. non-developers)',
|
|
4319
4375
|
questions: [
|
|
4320
4376
|
'그래서 30초 안에 뭘 해보면 되지?',
|
|
4321
4377
|
'비개발자가 터미널 명령 하나 없이 어떻게 사용하지?',
|
|
4322
4378
|
'기존 도구가 이미 있는데 이걸 쓸 이유가 뭐지?'
|
|
4323
4379
|
],
|
|
4324
|
-
|
|
4380
|
+
questionsEn: [
|
|
4381
|
+
'So, what can I actually try in 30 seconds?',
|
|
4382
|
+
'How does a non-developer use this without a single terminal command?',
|
|
4383
|
+
'Tools already exist — why use this one?'
|
|
4384
|
+
],
|
|
4385
|
+
affects: ['design'], affectsNote: '문서가 어렵다면 보통 제품 흐름(UX) 자체가 어렵다는 신호',
|
|
4386
|
+
affectsNoteEn: 'hard docs usually signal the product flow (UX) itself is hard'
|
|
4325
4387
|
},
|
|
4326
4388
|
test: {
|
|
4327
4389
|
title: '테스트', persona: '검증자',
|
|
4390
|
+
titleEn: 'tests', personaEn: 'verifier',
|
|
4328
4391
|
questions: [
|
|
4329
4392
|
'이 테스트는 실패할 수 있는 테스트인가? (assert(true) 아님)',
|
|
4330
4393
|
'주장한 테스트 개수/통과가 실측과 일치하는가?',
|
|
4331
4394
|
'테스트가 구현을 실제로 import/호출하는가?'
|
|
4332
4395
|
],
|
|
4333
|
-
|
|
4396
|
+
questionsEn: [
|
|
4397
|
+
'Can this test actually fail? (not assert(true))',
|
|
4398
|
+
'Do the claimed test count/pass match the real measured numbers?',
|
|
4399
|
+
'Does the test actually import/call the implementation?'
|
|
4400
|
+
],
|
|
4401
|
+
affects: ['code'], affectsNote: '테스트하기 어렵다면 코드가 복잡하다는 신호 — code 질문으로 돌아갈 것',
|
|
4402
|
+
affectsNoteEn: 'hard-to-test signals complex code — go back to the code questions'
|
|
4334
4403
|
},
|
|
4335
4404
|
security: {
|
|
4336
4405
|
title: '보안', persona: '공격자',
|
|
4406
|
+
titleEn: 'security', personaEn: 'attacker',
|
|
4337
4407
|
questions: [
|
|
4338
4408
|
'시크릿이 코드/커밋에 들어가지 않았는가?',
|
|
4339
4409
|
'이 입력을 악의적으로 주면 어떻게 되는가?',
|
|
4340
4410
|
'권한/경계를 한 단어 비틀기로 우회할 수 있는가?'
|
|
4341
4411
|
],
|
|
4342
|
-
|
|
4412
|
+
questionsEn: [
|
|
4413
|
+
'Are there no secrets in the code/commits?',
|
|
4414
|
+
'What happens if this input is given maliciously?',
|
|
4415
|
+
'Can a one-word twist bypass a permission/boundary?'
|
|
4416
|
+
],
|
|
4417
|
+
affects: ['code', 'test'], affectsNote: '보안 가드를 넣었다면 우회/오탐 테스트가 따라와야 함',
|
|
4418
|
+
affectsNoteEn: 'if you added a security guard, bypass/false-positive tests should follow'
|
|
4343
4419
|
}
|
|
4344
4420
|
};
|
|
4345
4421
|
// 1.19.3 (UR-0003 렌즈 완전판 v3): 프로젝트별 커스텀 렌즈 — .harness/quality-lenses.json 읽기-병합(쓰기 명령 없음, AI/사용자가 편집).
|
|
@@ -4392,24 +4468,32 @@ function lensCmd(domain, opts = {}) {
|
|
|
4392
4468
|
if (domain != null) domain = String(domain).trim().toLowerCase();
|
|
4393
4469
|
// 1.19.3: 내장 + 프로젝트 커스텀(.harness/quality-lenses.json) 병합 catalog.
|
|
4394
4470
|
const root = opts.root || arg('--path', process.cwd());
|
|
4471
|
+
const L = _uiLang(root); const t = (ko, en) => (L === 'en' ? en : ko); // 1.24.2 (UR-0010 Phase 8): lens 영어 opt-in
|
|
4395
4472
|
const catalog = _effectiveLensCatalog(root);
|
|
4396
4473
|
if (domain && !catalog[domain]) {
|
|
4397
|
-
return fail(`알 수 없는 렌즈: ${domain} — 유효값: ${Object.keys(catalog).join(', ')}`);
|
|
4474
|
+
return fail(t(`알 수 없는 렌즈: ${domain} — 유효값: ${Object.keys(catalog).join(', ')}`, `unknown lens: ${domain} — valid: ${Object.keys(catalog).join(', ')}`));
|
|
4398
4475
|
}
|
|
4399
4476
|
const picked = domain ? { [domain]: catalog[domain] } : catalog;
|
|
4400
4477
|
if (jsonMode) { log(JSON.stringify({ ok: true, lenses: picked }, null, 2)); return; }
|
|
4401
4478
|
const hasCustom = Object.values(catalog).some(l => l && (l._custom || l._customAdded));
|
|
4402
|
-
log(`# leerness lens — 분야별 자기질문 품질 렌즈 (v${VERSION})${hasCustom ? ' + 프로젝트 커스텀(.harness/quality-lenses.json)' : ''}`);
|
|
4403
|
-
log(`완료 선언 전 해당 분야 질문에 스스로 답해보세요. "그렇다(통과)"라고 답할 수 없으면 아직 완료가
|
|
4479
|
+
log(t(`# leerness lens — 분야별 자기질문 품질 렌즈 (v${VERSION})${hasCustom ? ' + 프로젝트 커스텀(.harness/quality-lenses.json)' : ''}`, `# leerness lens — quality self-question lenses (v${VERSION})${hasCustom ? ' + project custom (.harness/quality-lenses.json)' : ''}`));
|
|
4480
|
+
log(t(`완료 선언 전 해당 분야 질문에 스스로 답해보세요. "그렇다(통과)"라고 답할 수 없으면 아직 완료가 아닙니다.`, `Before declaring done, answer each domain's questions yourself. If you can't answer "yes (pass)", it's not done yet.`));
|
|
4404
4481
|
for (const [key, l] of Object.entries(picked)) {
|
|
4405
4482
|
log('');
|
|
4406
|
-
|
|
4407
|
-
l.
|
|
4408
|
-
|
|
4483
|
+
const title = (L === 'en' && l.titleEn) ? l.titleEn : l.title;
|
|
4484
|
+
const persona = (L === 'en' && l.personaEn) ? l.personaEn : l.persona;
|
|
4485
|
+
const note = (L === 'en' && l.affectsNoteEn) ? l.affectsNoteEn : l.affectsNote;
|
|
4486
|
+
const cflag = l._custom ? t(' [프로젝트]', ' [project]') : (l._customAdded ? t(' [+프로젝트 질문]', ' [+project questions]') : '');
|
|
4487
|
+
// en: builtin 영어 질문 + (커스텀 추가질문은 questions 의 builtin 개수 이후 — questionsEn 과 동일 개수 기준으로 분리)
|
|
4488
|
+
let qs = l.questions;
|
|
4489
|
+
if (L === 'en' && l.questionsEn) qs = l.questions.length > l.questionsEn.length ? [...l.questionsEn, ...l.questions.slice(l.questionsEn.length)] : l.questionsEn;
|
|
4490
|
+
log(`## ${key} (${title}) — ${t('페르소나', 'persona')}: ${persona}${cflag}`);
|
|
4491
|
+
qs.forEach((q, i) => log(` ${i + 1}. ${q}`));
|
|
4492
|
+
log(t(` ↔ 인과: ${key} 를 바꾸면 → ${(l.affects || []).join(', ') || '(없음)'} 질문도 다시 — ${note}`, ` ↔ causality: change ${key} → re-check ${(l.affects || []).join(', ') || '(none)'} too — ${note}`));
|
|
4409
4493
|
}
|
|
4410
4494
|
log('');
|
|
4411
|
-
log(`사용: leerness lens <${Object.keys(catalog).join('|')}> · 완료 검증과 함께: leerness verify-claim T-XXXX`);
|
|
4412
|
-
if (!hasCustom) log(`프로젝트 커스텀 렌즈: .harness/quality-lenses.json 에 { "domains": { "code": { "questions": ["..."] } } }
|
|
4495
|
+
log(t(`사용: leerness lens <${Object.keys(catalog).join('|')}> · 완료 검증과 함께: leerness verify-claim T-XXXX`, `Usage: leerness lens <${Object.keys(catalog).join('|')}> · with completion check: leerness verify-claim T-XXXX`));
|
|
4496
|
+
if (!hasCustom) log(t(`프로젝트 커스텀 렌즈: .harness/quality-lenses.json 에 { "domains": { "code": { "questions": ["..."] } } } 추가`, `Project custom lenses: add { "domains": { "code": { "questions": ["..."] } } } to .harness/quality-lenses.json`));
|
|
4413
4497
|
}
|
|
4414
4498
|
|
|
4415
4499
|
function commandsCmd(root) {
|
|
@@ -5298,14 +5382,15 @@ function requestsCmd(root, sub, ...rest) {
|
|
|
5298
5382
|
const dim = s => isTty ? `\x1b[2m${s}\x1b[0m` : s;
|
|
5299
5383
|
|
|
5300
5384
|
if (!sub || sub === 'help' || sub === '--help') {
|
|
5301
|
-
|
|
5385
|
+
const _L = _uiLang(root); const _t = (ko, en) => _L === 'en' ? en : ko; // 1.23.2 (UR-0010 Phase 7)
|
|
5386
|
+
log(_t(`# leerness requests (1.9.207) — 사용자 요청 누락 확인 절차`, `# leerness requests — track missing user requests`));
|
|
5302
5387
|
log('');
|
|
5303
|
-
log(` audit → 누락 후보 + tracked + stale 보고 (--json 가능)`);
|
|
5304
|
-
log(` add "<text>" → 사용자 요청 수동
|
|
5305
|
-
log(` list → 전체 요청 출력 (--json 가능, --status open|completed|dropped)`);
|
|
5306
|
-
log(` complete <id> → 요청 완료 표시 (예: UR-0003)`);
|
|
5307
|
-
log(` drop <id> → 요청 드롭
|
|
5308
|
-
log(` auto-complete → "Round X.Y.Z — 구현 완료" 패턴 자동 감지 (default: dry-run, --apply 시 적용) [1.9.223]`);
|
|
5388
|
+
log(_t(` audit → 누락 후보 + tracked + stale 보고 (--json 가능)`, ` audit → report missing candidates + tracked + stale (--json)`));
|
|
5389
|
+
log(_t(` add "<text>" → 사용자 요청 수동 기록`, ` add "<text>" → manually record a user request`));
|
|
5390
|
+
log(_t(` list → 전체 요청 출력 (--json 가능, --status open|completed|dropped)`, ` list → list all requests (--json, --status open|completed|dropped)`));
|
|
5391
|
+
log(_t(` complete <id> → 요청 완료 표시 (예: UR-0003)`, ` complete <id> → mark a request completed (e.g. UR-0003)`));
|
|
5392
|
+
log(_t(` drop <id> → 요청 드롭 표시`, ` drop <id> → mark a request dropped`));
|
|
5393
|
+
log(_t(` auto-complete → "Round X.Y.Z — 구현 완료" 패턴 자동 감지 (default: dry-run, --apply 시 적용) [1.9.223]`, ` auto-complete → auto-detect "Round X.Y.Z delivered" patterns (default: dry-run, --apply to apply)`));
|
|
5309
5394
|
return;
|
|
5310
5395
|
}
|
|
5311
5396
|
|
|
@@ -5551,13 +5636,14 @@ function constraintsCmd(root, sub, ...rest) {
|
|
|
5551
5636
|
const dim = s => isTty ? `\x1b[2m${s}\x1b[0m` : s;
|
|
5552
5637
|
|
|
5553
5638
|
if (!sub || sub === 'help' || sub === '--help') {
|
|
5554
|
-
|
|
5639
|
+
const _L = _uiLang(root); const _t = (ko, en) => _L === 'en' ? en : ko; // 1.23.2 (UR-0010 Phase 7)
|
|
5640
|
+
log(_t(`# leerness constraints (1.9.208) — 플랫폼/API 제약 사전 체크`, `# leerness constraints — pre-check platform/API constraints`));
|
|
5555
5641
|
log('');
|
|
5556
|
-
log(` list → 등록된 모든 플랫폼 catalog 출력 (--json 가능)`);
|
|
5557
|
-
log(` check "<request>" → 사용자 요청에서 플랫폼 매칭 → 제약 보고 (--json 가능)`);
|
|
5642
|
+
log(_t(` list → 등록된 모든 플랫폼 catalog 출력 (--json 가능)`, ` list → list all registered platform catalogs (--json)`));
|
|
5643
|
+
log(_t(` check "<request>" → 사용자 요청에서 플랫폼 매칭 → 제약 보고 (--json 가능)`, ` check "<request>" → match platforms in a request → report constraints (--json)`));
|
|
5558
5644
|
log(` add <id> --constraint "kind:detail" --alias name`);
|
|
5559
5645
|
log('');
|
|
5560
|
-
log(dim(` 예: leerness constraints check "Stripe API 연동 결제 모듈"`));
|
|
5646
|
+
log(dim(_t(` 예: leerness constraints check "Stripe API 연동 결제 모듈"`, ` e.g. leerness constraints check "Stripe API payment integration"`)));
|
|
5561
5647
|
return;
|
|
5562
5648
|
}
|
|
5563
5649
|
|
|
@@ -5737,15 +5823,16 @@ function wakeupIntervalCmd(root, sub, val) {
|
|
|
5737
5823
|
const dim = s => isTty ? `\x1b[2m${s}\x1b[0m` : s;
|
|
5738
5824
|
|
|
5739
5825
|
if (!sub || sub === 'help' || sub === '--help') {
|
|
5740
|
-
|
|
5826
|
+
const _L = _uiLang(root); const _t = (ko, en) => _L === 'en' ? en : ko; // 1.23.2 (UR-0010 Phase 7)
|
|
5827
|
+
log(_t(`# leerness wakeup-interval (1.9.210) — adaptive wakeup 간격`, `# leerness wakeup-interval — adaptive wakeup interval`));
|
|
5741
5828
|
log('');
|
|
5742
|
-
log(` get → 현재 권장 interval + stats (--json 가능)`);
|
|
5743
|
-
log(` set <secs> → override 설정 (예: leerness wakeup-interval set 900)`);
|
|
5744
|
-
log(` auto → override 해제 + 자동 계산
|
|
5745
|
-
log(` history → 최근 fire 이력
|
|
5746
|
-
log(` record <kind> → fire 기록 (user-trigger / auto / wakeup-miss)`);
|
|
5829
|
+
log(_t(` get → 현재 권장 interval + stats (--json 가능)`, ` get → current recommended interval + stats (--json)`));
|
|
5830
|
+
log(_t(` set <secs> → override 설정 (예: leerness wakeup-interval set 900)`, ` set <secs> → set an override (e.g. leerness wakeup-interval set 900)`));
|
|
5831
|
+
log(_t(` auto → override 해제 + 자동 계산 모드`, ` auto → clear override + auto-compute mode`));
|
|
5832
|
+
log(_t(` history → 최근 fire 이력 출력`, ` history → recent fire history`));
|
|
5833
|
+
log(_t(` record <kind> → fire 기록 (user-trigger / auto / wakeup-miss)`, ` record <kind> → record a fire (user-trigger / auto / wakeup-miss)`));
|
|
5747
5834
|
log('');
|
|
5748
|
-
log(dim(` opt-out: env LEERNESS_FIXED_INTERVAL=1500 (초) 또는 set <secs>`));
|
|
5835
|
+
log(dim(_t(` opt-out: env LEERNESS_FIXED_INTERVAL=1500 (초) 또는 set <secs>`, ` opt-out: env LEERNESS_FIXED_INTERVAL=1500 (seconds) or set <secs>`)));
|
|
5749
5836
|
return;
|
|
5750
5837
|
}
|
|
5751
5838
|
|
|
@@ -6113,15 +6200,16 @@ function idempotencyCmd(root, sub) {
|
|
|
6113
6200
|
const dim = s => isTty ? `\x1b[2m${s}\x1b[0m` : s;
|
|
6114
6201
|
|
|
6115
6202
|
if (!sub || sub === 'help' || sub === '--help') {
|
|
6116
|
-
|
|
6203
|
+
const _L = _uiLang(root); const _t = (ko, en) => _L === 'en' ? en : ko; // 1.23.2 (UR-0010 Phase 7)
|
|
6204
|
+
log(_t(`# leerness idempotency (1.9.212) — 멱등성 위반 탐지`, `# leerness idempotency — detect idempotency violations`));
|
|
6117
6205
|
log('');
|
|
6118
|
-
log(` audit → 워크스페이스 멱등성 점검 (rules / tasks / user-requests / wakeups) (--json 가능)`);
|
|
6119
|
-
log(` audit --auto-fix → task 완전중복 행 제거 + active 동일텍스트 dropped 처리 + user-request open 중복 정리 (1.9.293)`);
|
|
6206
|
+
log(_t(` audit → 워크스페이스 멱등성 점검 (rules / tasks / user-requests / wakeups) (--json 가능)`, ` audit → check workspace idempotency (rules / tasks / user-requests / wakeups) (--json)`));
|
|
6207
|
+
log(_t(` audit --auto-fix → task 완전중복 행 제거 + active 동일텍스트 dropped 처리 + user-request open 중복 정리 (1.9.293)`, ` audit --auto-fix → remove exact-duplicate tasks + mark same-text active as dropped + dedup open user-requests`));
|
|
6120
6208
|
log('');
|
|
6121
|
-
log(dim(` dedup 적용 영역: ruleAdd / taskAdd (1.9.212) + _recordUserRequest (1.9.207) + _recordWakeup (1.9.205)`));
|
|
6122
|
-
log(dim(` --auto-fix 안전: 완전 동일 행만 제거 / 동일텍스트는 status=dropped 로 보존(id 유지) / git 회복 가능 /
|
|
6123
|
-
log(dim(` 자동화: drift check --auto-fix 가 idempotency 중복도 자동 정리 (1.9.293)`));
|
|
6124
|
-
log(dim(` opt-out: --force 플래그로 dedup 우회
|
|
6209
|
+
log(dim(_t(` dedup 적용 영역: ruleAdd / taskAdd (1.9.212) + _recordUserRequest (1.9.207) + _recordWakeup (1.9.205)`, ` dedup applies to: ruleAdd / taskAdd + _recordUserRequest + _recordWakeup`)));
|
|
6210
|
+
log(dim(_t(` --auto-fix 안전: 완전 동일 행만 제거 / 동일텍스트는 status=dropped 로 보존(id 유지) / git 회복 가능 / 멱등`, ` --auto-fix safety: removes only exact dupes / same-text kept as status=dropped (id preserved) / git-recoverable / idempotent`)));
|
|
6211
|
+
log(dim(_t(` 자동화: drift check --auto-fix 가 idempotency 중복도 자동 정리 (1.9.293)`, ` automation: drift check --auto-fix also dedups idempotency violations`)));
|
|
6212
|
+
log(dim(_t(` opt-out: --force 플래그로 dedup 우회 가능`, ` opt-out: pass --force to bypass dedup`)));
|
|
6125
6213
|
return;
|
|
6126
6214
|
}
|
|
6127
6215
|
|
|
@@ -6188,14 +6276,15 @@ function intentCmd(root, sub, ...rest) {
|
|
|
6188
6276
|
const dim = s => isTty ? `\x1b[2m${s}\x1b[0m` : s;
|
|
6189
6277
|
|
|
6190
6278
|
if (!sub || sub === 'help' || sub === '--help') {
|
|
6191
|
-
|
|
6279
|
+
const _L = _uiLang(root); const _t = (ko, en) => _L === 'en' ? en : ko; // 1.23.2 (UR-0010 Phase 7)
|
|
6280
|
+
log(_t(`# leerness intent (1.9.213) — 사용자 의도 파악 + scope expansion 게이트`, `# leerness intent — infer user intent + scope-expansion gate`));
|
|
6192
6281
|
log('');
|
|
6193
|
-
log(` classify "<request>" → intent 분류 (precise/broad/default) + 신호 (--json 가능)`);
|
|
6194
|
-
log(` expand "<request>" → 도메인 탐지 + 확장 후보 dry-run (--json 가능)`);
|
|
6195
|
-
log(` domains → 등록된 도메인 catalog 출력 (game/web/api/cli/data)`);
|
|
6282
|
+
log(_t(` classify "<request>" → intent 분류 (precise/broad/default) + 신호 (--json 가능)`, ` classify "<request>" → classify intent (precise/broad/default) + signals (--json)`));
|
|
6283
|
+
log(_t(` expand "<request>" → 도메인 탐지 + 확장 후보 dry-run (--json 가능)`, ` expand "<request>" → detect domain + expansion candidates (dry-run, --json)`));
|
|
6284
|
+
log(_t(` domains → 등록된 도메인 catalog 출력 (game/web/api/cli/data)`, ` domains → list registered domain catalog (game/web/api/cli/data)`));
|
|
6196
6285
|
log('');
|
|
6197
|
-
log(dim(` 3원칙: (1) Always-Off Opt-In (2) Dry-run 기본 (실행 X) (3) 명시 vs 추론 분리
|
|
6198
|
-
log(dim(` 예: leerness intent expand "맵과 캐릭터 + 기본 게임 기능 만들어줘"`));
|
|
6286
|
+
log(dim(_t(` 3원칙: (1) Always-Off Opt-In (2) Dry-run 기본 (실행 X) (3) 명시 vs 추론 분리 라벨링`, ` 3 principles: (1) always-off opt-in (2) dry-run by default (no execution) (3) explicit vs inferred labeling`)));
|
|
6287
|
+
log(dim(_t(` 예: leerness intent expand "맵과 캐릭터 + 기본 게임 기능 만들어줘"`, ` e.g. leerness intent expand "build a map + characters + basic game features"`)));
|
|
6199
6288
|
return;
|
|
6200
6289
|
}
|
|
6201
6290
|
|
|
@@ -7598,8 +7687,9 @@ function route(name) {
|
|
|
7598
7687
|
|
|
7599
7688
|
function status(root) {
|
|
7600
7689
|
root = absRoot(root);
|
|
7690
|
+
const _L = _uiLang(root); const t = (ko, en) => (_L === 'en' ? en : ko); // 1.23.1 (UR-0010 Phase 6)
|
|
7601
7691
|
// 1.9.434 (11th 외부평가 Opus P2, UR-0136): 미존재 경로는 healthy 위조 금지 — failJson + exit 1.
|
|
7602
|
-
if (!exists(root)) { failJson(has('--json'), 'path_not_found', `경로 없음: ${root}`); return; }
|
|
7692
|
+
if (!exists(root)) { failJson(has('--json'), 'path_not_found', t(`경로 없음: ${root}`, `path not found: ${root}`)); return; }
|
|
7603
7693
|
const verF = path.join(root,'.harness/HARNESS_VERSION');
|
|
7604
7694
|
const ver = exists(verF) ? read(verF).trim() : 'not installed';
|
|
7605
7695
|
const lang = exists(path.join(root,'.harness/LANGUAGE')) ? read(path.join(root,'.harness/LANGUAGE')).trim() : 'ko';
|
|
@@ -7610,7 +7700,7 @@ function status(root) {
|
|
|
7610
7700
|
const missing = files.filter(f => !exists(path.join(root,f)));
|
|
7611
7701
|
// 1.9.384 (5번째 외부평가/UR-0085): --json 일관성 — AI 에이전트용 구조화 출력.
|
|
7612
7702
|
// 1.9.418 (9th 외부평가 Codex P2): healthy 의 의미를 명시(설치 파일 존재 ≠ 프로젝트 안전). 프로젝트 안전은 gate/scan secrets 사용.
|
|
7613
|
-
if (has('--json')) { log(JSON.stringify({ version: ver, language: lang, minimal: isMinimal, scope: 'install', total: files.length, present: files.length - missing.length, missing, healthy: missing.length === 0, healthyMeaning: '설치 파일 존재 여부(프로젝트 안전 아님 — 보안/품질은 leerness gate / scan secrets 사용)' }, null, 2)); return; }
|
|
7703
|
+
if (has('--json')) { log(JSON.stringify({ version: ver, language: lang, minimal: isMinimal, scope: 'install', total: files.length, present: files.length - missing.length, missing, healthy: missing.length === 0, healthyMeaning: t('설치 파일 존재 여부(프로젝트 안전 아님 — 보안/품질은 leerness gate / scan secrets 사용)', 'install-file presence only (not project safety — use leerness gate / scan secrets for security/quality)') }, null, 2)); return; }
|
|
7614
7704
|
log(`Leerness: ${ver}${isMinimal ? ' (minimal)' : ''}`);
|
|
7615
7705
|
log(`Files: ${files.length - missing.length}/${files.length}`);
|
|
7616
7706
|
if (missing.length) missing.forEach(x => warn('missing: ' + x));
|
|
@@ -12347,13 +12437,15 @@ function _retroAggregate(root) {
|
|
|
12347
12437
|
};
|
|
12348
12438
|
}
|
|
12349
12439
|
|
|
12350
|
-
function _retroOneLine(agg) {
|
|
12440
|
+
function _retroOneLine(agg, lang) {
|
|
12441
|
+
// 1.24.1 (UR-0010): 선택적 lang — en 시 한 줄 요약 영어. 미지정 시 ko(기존 호출부 무영향).
|
|
12442
|
+
const t = (ko, en) => (lang === 'en' ? en : ko);
|
|
12351
12443
|
const parts = [];
|
|
12352
12444
|
const done = agg.statusCounts.done;
|
|
12353
12445
|
const total = agg.totalTasks;
|
|
12354
|
-
if (total) parts.push(`완료 ${done}/${total} (${Math.round(done / total * 100)}%)`);
|
|
12355
|
-
if (agg.totalSkillUsage) parts.push(`스킬 ${agg.skillUsage.length}종 / 사용 ${agg.totalSkillUsage}회 / 최적화 ${agg.totalOptimizations}
|
|
12356
|
-
if (agg.activeRules) parts.push(`룰 ${agg.activeRules}건 활성 (${agg.verifiedRules} 검증됨)`);
|
|
12446
|
+
if (total) parts.push(t(`완료 ${done}/${total} (${Math.round(done / total * 100)}%)`, `done ${done}/${total} (${Math.round(done / total * 100)}%)`));
|
|
12447
|
+
if (agg.totalSkillUsage) parts.push(t(`스킬 ${agg.skillUsage.length}종 / 사용 ${agg.totalSkillUsage}회 / 최적화 ${agg.totalOptimizations}건`, `skills ${agg.skillUsage.length} / uses ${agg.totalSkillUsage} / optimizations ${agg.totalOptimizations}`));
|
|
12448
|
+
if (agg.activeRules) parts.push(t(`룰 ${agg.activeRules}건 활성 (${agg.verifiedRules} 검증됨)`, `rules ${agg.activeRules} active (${agg.verifiedRules} verified)`));
|
|
12357
12449
|
if (agg.durations.length >= 4) {
|
|
12358
12450
|
const mid = Math.floor(agg.durations.length / 2);
|
|
12359
12451
|
const a = agg.durations.slice(0, mid).reduce((x, y) => x + y, 0) / mid;
|
|
@@ -12361,10 +12453,10 @@ function _retroOneLine(agg) {
|
|
|
12361
12453
|
if (a > 0) {
|
|
12362
12454
|
const delta = ((b - a) / a) * 100;
|
|
12363
12455
|
const sign = delta > 0 ? '+' : '';
|
|
12364
|
-
parts.push(`검증 ${Math.round(a)}ms→${Math.round(b)}ms (${sign}${delta.toFixed(1)}%)`);
|
|
12456
|
+
parts.push(t(`검증 ${Math.round(a)}ms→${Math.round(b)}ms (${sign}${delta.toFixed(1)}%)`, `verify ${Math.round(a)}ms→${Math.round(b)}ms (${sign}${delta.toFixed(1)}%)`));
|
|
12365
12457
|
}
|
|
12366
12458
|
}
|
|
12367
|
-
parts.push(`결정 ${agg.decisionBlocks}건
|
|
12459
|
+
parts.push(t(`결정 ${agg.decisionBlocks}건 누적`, `decisions ${agg.decisionBlocks} accumulated`));
|
|
12368
12460
|
return parts.join(' · ');
|
|
12369
12461
|
}
|
|
12370
12462
|
|
|
@@ -13326,10 +13418,11 @@ function _autoRoadmap(root, trigger) {
|
|
|
13326
13418
|
const outFile = path.resolve(cfg.outFile || path.join(root, 'roadmap.html'));
|
|
13327
13419
|
const data = _roadmapData(root);
|
|
13328
13420
|
writeUtf8(outFile, _roadmapHTML(data));
|
|
13329
|
-
|
|
13421
|
+
const _en = _uiLang(root) === 'en'; // 1.24.1 (UR-0010): roadmap 로그 en
|
|
13422
|
+
log(_en ? `✓ roadmap.html auto-updated (${trigger}) — ${rel(root, outFile)}` : `✓ roadmap.html 자동 갱신 (${trigger}) — ${rel(root, outFile)}`);
|
|
13330
13423
|
return true;
|
|
13331
13424
|
} catch (e) {
|
|
13332
|
-
warn('roadmap 자동 갱신 실패: ' + (e && e.message ? e.message : e));
|
|
13425
|
+
warn((_uiLang(root) === 'en' ? 'roadmap auto-update failed: ' : 'roadmap 자동 갱신 실패: ') + (e && e.message ? e.message : e));
|
|
13333
13426
|
return false;
|
|
13334
13427
|
}
|
|
13335
13428
|
}
|
|
@@ -19604,7 +19697,102 @@ const _diag = require('../lib/diagnostics');
|
|
|
19604
19697
|
function doctorCmd(opts = {}) { return _diag.doctorCmd(opts, { VERSION, _selfTestCases, _detectShellCtx, _mcpToolCount, has, harnessPath: __filename }); }
|
|
19605
19698
|
function whichCmd() { return _diag.whichCmd({ VERSION, has, harnessPath: __filename }); }
|
|
19606
19699
|
|
|
19700
|
+
// 1.23.1 (UR-0010 Phase 6): 영어 큐레이트 도움말 — 한국어 help 의 줄별 번역이 아니라, 카테고리별로 정리한 별도 영어판.
|
|
19701
|
+
// 레거시 버전태그(1.9.x) 군더더기를 빼고 영어 사용자가 읽기 쉽게. 전체 전수 목록은 `leerness commands`.
|
|
19702
|
+
// 한국어 help() 는 그대로 유지(기본 ko, e2e 무회귀). 영어는 --language en / LEERNESS_LANG=en opt-in.
|
|
19703
|
+
function _helpEn() {
|
|
19704
|
+
log(`Leerness v${VERSION}
|
|
19705
|
+
|
|
19706
|
+
The AI-coding operations layer that makes "done" require evidence.
|
|
19707
|
+
Korean-first by default; this English help shows with --language en or LEERNESS_LANG=en.
|
|
19708
|
+
|
|
19709
|
+
Usage: leerness <command> [path] [options]
|
|
19710
|
+
|
|
19711
|
+
SETUP & UPDATE
|
|
19712
|
+
init [path] [--language auto|ko|en] [--skills recommended|all|a,b] [--minimal] [--yes]
|
|
19713
|
+
Install the .harness/ workspace into your project
|
|
19714
|
+
migrate [path] [--dry-run] [--force] Non-destructive cross-version migration
|
|
19715
|
+
migrate audit|apply|plan [path] [--json] Diagnose / backfill / compare migration
|
|
19716
|
+
update [path] [--check|--yes|--force] Auto-detect version + migrate
|
|
19717
|
+
auto-update install [path] Install the auto-update hook
|
|
19718
|
+
path-setup [--apply] Register the leerness CLI on PATH
|
|
19719
|
+
|
|
19720
|
+
STATUS & DIAGNOSTICS
|
|
19721
|
+
status [path] Install status (files present)
|
|
19722
|
+
health [path] | doctor [path] Install/state diagnostics
|
|
19723
|
+
verify [path] Required-file verification
|
|
19724
|
+
which [--json] Resolve current binary/version (npm cache conflicts)
|
|
19725
|
+
selftest [--json] Core-function integrity self-check (CI-friendly)
|
|
19726
|
+
pulse | milestones | round-history [path] Combined progress metrics
|
|
19727
|
+
whats-new [path] Recent version changes
|
|
19728
|
+
|
|
19729
|
+
VERIFICATION (evidence-gated "done")
|
|
19730
|
+
verify-claim <T-ID> [--run-tests] [--test-cmd "..."] [--json]
|
|
19731
|
+
Check evidence vs reality (stub / fake-test / inflated-count detection)
|
|
19732
|
+
contract verify <spec.md> <impl.js> [--json] Spec <-> implementation match
|
|
19733
|
+
verify-code [path] [--build] [--bench] Run tests/lint/typecheck, record evidence
|
|
19734
|
+
gate [path] One-call CI gate: verify + audit + scan + encoding + lazy
|
|
19735
|
+
lens [code|design|docs|test|security] [--json] Quality self-question lenses
|
|
19736
|
+
|
|
19737
|
+
SECURITY & HYGIENE
|
|
19738
|
+
scan secrets [path] Committed-secret detection
|
|
19739
|
+
encoding check [path] UTF-8 / BOM / CP949 / shell-script encoding
|
|
19740
|
+
audit [path] [--fix] Consistency + plan/progress alignment
|
|
19741
|
+
lazy detect [path] [--auto-track] Anti-laziness evaluation
|
|
19742
|
+
shell-guard "<command>" [--json] Shell-compatibility linter (PowerShell 5.1 etc.)
|
|
19743
|
+
|
|
19744
|
+
HANDOFF & SESSION
|
|
19745
|
+
handoff [path] [--compact] [--all-apps] [--json] Session-start context in one call
|
|
19746
|
+
session close [path] Closing report + auto handoff
|
|
19747
|
+
context [path] [--json] Agent onboarding context
|
|
19748
|
+
retro | insights [path] [--json] Retrospective / cumulative stats
|
|
19749
|
+
|
|
19750
|
+
MEMORY (canonical JSON + markdown projections)
|
|
19751
|
+
task list|add|update|drop|fix-evidence|relink [args]
|
|
19752
|
+
plan show|init|add|drop|progress|sync [args]
|
|
19753
|
+
decision add "<title>" [--reason ...] | decision list|drop <id>
|
|
19754
|
+
lesson save "<text>" [--tag t] | lesson list|drop <id>
|
|
19755
|
+
rule add "<text>" --trigger every-session|every-commit|... | rule list|pause|resume|remove
|
|
19756
|
+
requests audit|add|list|complete|drop User-request tracking (UR-XXXX)
|
|
19757
|
+
memory search "query" [--include-code] [--limit N]
|
|
19758
|
+
memory archive list|restore [args]
|
|
19759
|
+
lessons [--query <k>] | brainstorm "<topic>"
|
|
19760
|
+
|
|
19761
|
+
SKILLS
|
|
19762
|
+
skill list|info <name>|use <id>|remove <id>
|
|
19763
|
+
skill learn <id> --doc <url> --command "..." --capability "..."
|
|
19764
|
+
skill install <SKILL.md|dir|url> | skill discover --preset vercel|anthropic
|
|
19765
|
+
skill consolidate [--threshold 0.3]
|
|
19766
|
+
|
|
19767
|
+
AGENTS & PROVIDERS (opt-in)
|
|
19768
|
+
agents list|check|quota | agents dispatch "<task>" --to <id> | agents multi "<task>"
|
|
19769
|
+
provider list|add|remove [args]
|
|
19770
|
+
setup-agents [path] [--yes]
|
|
19771
|
+
team list|add|show|remove|preview|deploy <id> [...] (deploy is double-gated)
|
|
19772
|
+
|
|
19773
|
+
REUSE & IMPACT
|
|
19774
|
+
reuse autodetect|find|register [args] | reuse-map [path] [--json]
|
|
19775
|
+
impact <target> [--all] | deps <capability> [--run-tests]
|
|
19776
|
+
feature add|link|impact|list|show | graph [path] | guide [target]
|
|
19777
|
+
|
|
19778
|
+
RELEASE & OPS
|
|
19779
|
+
release bump|note|publish|channel|cadence [args]
|
|
19780
|
+
capabilities | install-safety [--json] | permissions list|set | creds list|register|check
|
|
19781
|
+
incident list|show|handle | deploy auto | runs list|show | webhook serve
|
|
19782
|
+
roadmap [path] [--out f.html] | roadmap auto on|off|status
|
|
19783
|
+
|
|
19784
|
+
MORE
|
|
19785
|
+
commands [--json] Full, exhaustive command list
|
|
19786
|
+
help | --help | -h This help
|
|
19787
|
+
--version | -v Version only
|
|
19788
|
+
|
|
19789
|
+
Docs: https://www.npmjs.com/package/leerness | https://leerness.pages.dev
|
|
19790
|
+
`);
|
|
19791
|
+
}
|
|
19792
|
+
|
|
19607
19793
|
function help() {
|
|
19794
|
+
// 1.23.1 (UR-0010 Phase 6): 영어 opt-in 시 큐레이트 영어판. 기본(ko) 은 아래 한국어 help 그대로.
|
|
19795
|
+
if (_uiLang(arg('--path', process.cwd())) === 'en') { _helpEn(); return; }
|
|
19608
19796
|
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/agy/copilot)\n leerness agents dispatch "<task>" --to <id> # 1.9.30 활성 CLI 대상 실행 명령 생성 (실 호출 X, 사용자 실행)\n leerness agents multi "<task>" [--only c1,c2] [--write] [--execute] [--timeout 60] # 1.9.152/156 활성 N개 일괄 dispatch (--execute: 실 spawn + consensus)\n leerness provider list|add|remove [args] # 1.9.157 Provider Registry — 사용자 정의 CLI provider 동적 추가 (OpenRouter/Bedrock 흡수)\n leerness agents dispatch "<task>" --multi # 1.9.152 multi 모드 alias (또는 --to all)\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 which [--json] # 1.9.164 진단: 현재 실행 경로/버전 + npm 캐시 + PATH 후보 (구버전 충돌 해결)\n leerness selftest [--json] # 1.9.258 코어 함수 무결성 자가 검증 (설치 손상/부분설치 감지, CI 친화 exit 1)\n leerness shell-guard "<command>" [--json] # 1.9.260 터미널 명령 셸 호환성 린터 (PowerShell 5.1 && 미지원 등 실행 전 감지, UR-0020)\n leerness shell-guard --record --cmd "..." --exit N # 1.9.260 실패한 터미널 명령 기록 → 다음 분석 시 회수\n leerness path-setup [--apply] [--json] # 1.9.254 leerness CLI PATH 자동 등록 (npm global bin 미등록 시)\n leerness web check|screenshot|extract <url> [--out file.png] [--selector "css"] # 1.9.165 playwright bridge (opt-in: npm i -g playwright + permissions.browser)\n leerness pc check|click|type|screenshot [--x N --y N] [--text "s"] [--out f.png] # 1.9.166 robotjs/nut-tree bridge (opt-in: npm i -g robotjs + permissions.mouse/keyboard, ⚠ full 모드 권장)\n leerness lsp check|symbols|references <file/name> [--in dir] [--json] # 1.9.167 LSP 어댑터 MVP (typescript opt-in + regex fallback, 코드 인텔리전스)\n leerness review-request "<request>" [--json] # 1.9.176 사용자 요청 사전 검토 (충돌/재사용/효율/권장 단계 — 사용자 명시)\n leerness contract verify <spec.md> <impl.js> [--json] # 1.9.35 명세 ↔ 구현 일치 검사 (함수/필드)\n leerness reuse autodetect [path] [--apply] [--json] # 1.9.35 src/*.js의 module.exports → reuse-map 후보 등록\n leerness audit [path] [--fix] # 1.9.35 --fix: session-handoff/current-state 자동 갱신\n leerness verify-claim <T-ID> ... [--strict-claims] # 1.9.26 verify-claim에 낙관적 표시 자동 검사 통합
|
|
19609
19797
|
leerness lens [code|design|docs|test|security] [--json] # 1.18.3 분야별 자기질문 품질 렌즈 + 분야간 인과관계 (완료 선언 전 자가 점검)\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 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
|
|
19610
19798
|
leerness retro [path] [--days 7] [--all-apps] [--include p1,p2] [--json] # 회고 (1.9.13~1.9.16)
|
|
@@ -20054,7 +20242,14 @@ async function main() {
|
|
|
20054
20242
|
feature: 'feature add "<이름>" | feature list | feature show <ID> | feature link <A> <B> | feature impact <ID>',
|
|
20055
20243
|
memory: 'memory search "<키>" [--json] | memory status | memory archive | memory restore',
|
|
20056
20244
|
};
|
|
20057
|
-
|
|
20245
|
+
// 1.23.2 (UR-0010 Phase 7): 영어 자리표시자 병렬맵 — ko 맵은 불변(e2e 안전), en 은 <text>/<trigger>/<key>/<name>.
|
|
20246
|
+
const _GROUP_USAGE_EN = {
|
|
20247
|
+
rule: 'rule add "<text>" --trigger <trigger> | rule list | rule pause/resume/remove <ID> | rule verify',
|
|
20248
|
+
skill: 'skill list | skill add <id> | skill use <id> | skill search "<key>" | skill match "<text>"',
|
|
20249
|
+
feature: 'feature add "<name>" | feature list | feature show <ID> | feature link <A> <B> | feature impact <ID>',
|
|
20250
|
+
memory: 'memory search "<key>" [--json] | memory status | memory archive | memory restore',
|
|
20251
|
+
};
|
|
20252
|
+
if (_GROUP_USAGE[cmd] && !args[1]) { const _gu = _uiLang(arg('--path', process.cwd())) === 'en' ? `${cmd} subcommand required — usage: leerness ${_GROUP_USAGE_EN[cmd]}` : `${cmd} 하위명령 필요 — 사용법: leerness ${_GROUP_USAGE[cmd]}`; failJson(has('--json'), 'subcommand_required', _gu); return; }
|
|
20058
20253
|
// 1.9.437 (11th 외부평가 Codex P2, UR-0138): --json 모드 unknown command 도 순수 JSON.
|
|
20059
20254
|
failJson(has('--json'), 'unknown_command', `알 수 없는 명령: ${cmd} (leerness --help 로 전체 명령 확인)`);
|
|
20060
20255
|
return;
|
package/lib/session-close.js
CHANGED
|
@@ -54,7 +54,7 @@ function sessionClose(root, opts = {}, deps = {}) {
|
|
|
54
54
|
if (_closeSecrets) log(t(` 🚨 마감 보안: 커밋 대상 시크릿 ${_closeSecrets}건 미해소 — clean 아님, leerness scan secrets 확인 후 마감 권장`, ` 🚨 close security: ${_closeSecrets} committed secret(s) unresolved — not clean, run leerness scan secrets before closing`));
|
|
55
55
|
|
|
56
56
|
function rowsToList(arr) {
|
|
57
|
-
if (!arr || !arr.length) return '- 없음';
|
|
57
|
+
if (!arr || !arr.length) return t('- 없음', '- none'); // 1.24.1 (UR-0010): en 보고 본문 정합(헤더는 이미 영어)
|
|
58
58
|
return arr.map(r => `- ${r.id} ${r.request} → next: ${r.nextAction}`).join('\n');
|
|
59
59
|
}
|
|
60
60
|
|
|
@@ -215,7 +215,7 @@ function sessionClose(root, opts = {}, deps = {}) {
|
|
|
215
215
|
writeSessionCounter(root, sc);
|
|
216
216
|
const agg = _retroAggregate(root);
|
|
217
217
|
log(t(`\n## 📈 진행 요약 (session #${sc.count})`, `\n## 📈 Progress summary (session #${sc.count})`));
|
|
218
|
-
log(` ${_retroOneLine(agg)}`);
|
|
218
|
+
log(` ${_retroOneLine(agg, uiLang)}`); // 1.24.1 (UR-0010): 진행 요약 한 줄 en
|
|
219
219
|
// 1.9.132: archive 활동 1줄 요약 — 마감 시점에 DELETE 활동 가시화 (handoff 7번째 회수와 symmetric)
|
|
220
220
|
try {
|
|
221
221
|
const hdSC = path.join(root, '.harness');
|