leerness 1.36.3 → 1.36.5

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,26 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.36.5 — 2026-07-09 — 정직성 감사: 성숙도 판정 과장 보정 (심층 멀티에이전트 정직성 감사 채택)
4
+
5
+ **게시본 1.36.4에 9개 사용자대면 표면 정직성 감사(멀티에이전트 35 + 적대적 반증) → 가장 강하게 수렴한 P1(성숙도 판정 과장) 보정.**
6
+
7
+ - `leerness health` 6능력 매트릭스: `overall N% (production-ready)` 는 **소스 문자열 존재 + 의존성 설치 여부 휴리스틱**의 평균일 뿐(미설치 의존성도 부분점수). "측정된/독립 성숙도 판정"으로 오독되지 않도록 **인라인 캐비엇** 추가.
8
+ - mcpTools 근거의 `CRUD 완성/CRUD complete` 제거 — 도구 수(≥50)는 기능적 CRUD 완결성을 증명하지 않음.
9
+ - REPL 환영창의 **하드코딩된 "72% production-ready · MCP 54 도구"** 고정/구식 수치 제거 → `leerness health` 참조로 대체.
10
+ - selftest 279 (신규 정직성 소스가드) + e2e 통과. self-ref 트랩 회피(split-literal).
11
+ - 정직 고지: 감사가 확인한 나머지 P2/P3 문구(policy "차단" enforce-ON 협조성, KO identity "허위완료 차단" vs EN, README "measures the real count" 방향성, "독립 검수"↔cross-model, encoding "passed" 스코프)는 정직성 백로그로 추적 — 이번 릴리스는 최고 수렴 P1에 집중.
12
+
13
+ ## 1.36.4 — 2026-07-09 — database 렌즈 recall: 내용 기반 DB 감지 (dogfood FN) — 평범한 이름의 DB 모듈도 렌즈 노출
14
+
15
+ **도그푸드에서 발견한 recall gap(FN) 소진.** 실사용(재고 서비스) 도중, `_lensDomainsForFiles` 가 **경로 휴리스틱**만 써서 `models/`·`.repository.`·`.sql` 등 관습적 이름의 파일만 `database` 도메인에 매핑함을 경험적으로 확인했다 — `inventory.safe.mjs`·`orders.occ.mjs` 처럼 실제로 SQLite 를 다루지만 이름에 단서가 없는 모듈은 `database` 렌즈가 **전혀 노출되지 않았다**(`["code"]` 로만 분류).
16
+
17
+ - 신규: `_isDbContentText` / `_anyDbContentInFiles` / `_withDbDomain` — verify-claim 이 주장 파일의 **내용**에 실제 DB 드라이버 import(`node:sqlite`/`pg`/`mysql2`/`better-sqlite3`/`typeorm`/`prisma` 등) 또는 산문엔 거의 없는 완결형 SQL 문장(`SELECT…FROM…WHERE`/`UPDATE…SET…WHERE`/`CREATE TABLE`/`INSERT INTO`/`ON CONFLICT`/`BEGIN IMMEDIATE`)이 있으면 `database` 렌즈를 보강 노출.
18
+ - FP 가드: 단일 키워드(`database`/`select`/`from`/`where` = 영어 단어)만으로는 안 켬 — 드라이버 import 또는 근접 다중 SQL 키워드 조합만. 산문/비-DB 코드 회귀 0(selftest 행위 검증).
19
+ - 안전: 코드 파일(.js/.mjs/.ts/.py 등)만, 512KB 이하만 읽음. path-기반 매핑은 그대로 두고 **추가 보강**만(비파괴). advisory 렌즈라 게이트 아님.
20
+ - codex FN검수 채택: **root 제한**(evidence 경로의 `../`·절대경로로 워크스페이스 밖 파일 읽기 차단, 심볼릭 링크 스킵 — P2) + **테스트 파일 제외**(SQL 담은 test 파일이 `test` 렌즈를 축출하지 않도록 — P3).
21
+ - 알려진 한계(정직 고지): 드라이버 import 가 타 파일에 있는 ORM 메서드체인 파일은 단일파일 내용분석으론 여전히 미탐(P3); `SELECT…FROM…WHERE` 형태의 드문 산문은 advisory FP 가능(저해, 게이트 아님).
22
+ - 검증: 실제 dogfood 4개 DB 모듈 전부 감지(전 false→true), 산문/README FP 0, ReDoS SAFE(<25ms @320KB), root 트래버설·테스트 제외 행위 검증. selftest 278 + full e2e 통과.
23
+
3
24
  ## 1.36.3 — 2026-07-08 — DB 안전성 렌즈 코어 승격 (race condition + ACID) — 사용자 명시 + codex 검수 채택
4
25
 
5
26
  - 신규 내장 품질 렌즈 도메인 `database` (8 자기질문: lost update / check-then-act TOCTOU / atomicity / DB 제약 / isolation+retry / durability / distribution). `leerness lens database` 로 호출, verify-claim 이 DB 파일 변경 시 인라인 노출.
package/README.md CHANGED
@@ -125,7 +125,7 @@ MIT
125
125
  <!-- leerness:project-readme:start -->
126
126
  ## Leerness Project Harness
127
127
 
128
- 이 프로젝트는 Leerness v1.36.3 하네스를 사용합니다. AI 에이전트는 작업 전 `leerness handoff`로 컨텍스트를 적재하고, 작업 후 `leerness check`/`leerness audit`/`leerness session close`를 수행해야 합니다.
128
+ 이 프로젝트는 Leerness v1.36.5 하네스를 사용합니다. AI 에이전트는 작업 전 `leerness handoff`로 컨텍스트를 적재하고, 작업 후 `leerness check`/`leerness audit`/`leerness session close`를 수행해야 합니다.
129
129
 
130
130
  ### 정체성 — AI 에이전트 운영 레이어 (UR-0030)
131
131
 
@@ -179,7 +179,7 @@ leerness memory restore decision <date|title>
179
179
 
180
180
  ### MCP server (외부 AI 통합)
181
181
 
182
- Leerness v1.36.3는 stdio JSON-RPC MCP server를 내장합니다 — Claude Code · Cursor · Codex CLI 등 외부 AI에 **86개 도구**를 노출:
182
+ Leerness v1.36.5는 stdio JSON-RPC MCP server를 내장합니다 — Claude Code · Cursor · Codex CLI 등 외부 AI에 **86개 도구**를 노출:
183
183
 
184
184
  ```jsonc
185
185
  // 카테고리별
@@ -200,7 +200,7 @@ Leerness v1.36.3는 stdio JSON-RPC MCP server를 내장합니다 — Claude Code
200
200
  `<<autonomous-loop-dynamic>>` 신호만 보내면 AI가:
201
201
  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) 다음 라운드 예약.
202
202
 
203
- 현재 누적: **70 라운드 (1.9.40 → 1.36.3)** · 매 라운드 GitHub release/태그 생성 · _reports/는 비공개 보존.
203
+ 현재 누적: **70 라운드 (1.9.40 → 1.36.5)** · 매 라운드 GitHub release/태그 생성 · _reports/는 비공개 보존.
204
204
 
205
205
  ### 성능 가이드 (1.9.140 측정)
206
206
 
@@ -238,6 +238,6 @@ leerness release pack --close --auto-main-push
238
238
  - `.harness/session-handoff.md`: 다음 세션 인수인계 (자동 작성)
239
239
  - `.harness/lessons.md` / `decisions.md` / `rules.md`: 영구 메모리 (5 surface)
240
240
 
241
- Last synced by Leerness v1.36.3: 2026-07-08
241
+ Last synced by Leerness v1.36.5: 2026-07-09
242
242
  <!-- leerness:project-readme:end -->
243
243
 
package/bin/leerness.js CHANGED
@@ -33,7 +33,7 @@ const { _evidenceQuality, _parseEvidenceStats, _shellGuardAnalyze, _claimFileInG
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
  const { findCorruptedStateJson: _findCorruptedStateJson } = require('../lib/state-integrity'); // 1.36.1 (클린룸 리뷰 FN): .harness/*.json 상태 무결성 (audit/health/check 공유)
35
35
 
36
- const VERSION = '1.36.3';
36
+ const VERSION = '1.36.5';
37
37
 
38
38
  // 1.9.290 (UR-0037, Codex gpt-5.5 #4 수렴): CLI 전용 부작용은 require 시 실행하지 않는다.
39
39
  // 이전: warning listener 제거 / NODE_OPTIONS 변경 / chcp IIFE 가 top-level 즉시 실행 → require('harness') 시 호스트 프로세스 오염.
@@ -3914,6 +3914,40 @@ function _selfTestCases() {
3914
3914
  && eq(F(['README.md']), ['docs']);
3915
3915
  return catOk && mapOk;
3916
3916
  } },
3917
+ { name: 'DB 렌즈 recall (dogfood FN, 1.36.4): 내용기반 감지 — 평범한 이름의 DB 모듈 잡고 산문 FP 0 (행위)', run: () => {
3918
+ const T = _isDbContentText, W = _withDbDomain;
3919
+ const eq = (a, b) => JSON.stringify(a) === JSON.stringify(b);
3920
+ // 잡아야: 드라이버 import + 완결형 SQL 문장(SELECT…FROM…WHERE / UPDATE…SET…WHERE) + DDL/트랜잭션 토큰
3921
+ const hit = T("import { DatabaseSync } from 'node:sqlite'")
3922
+ && T("const pg = require('pg')")
3923
+ && T("db.prepare('SELECT * FROM product WHERE id = ?')")
3924
+ && T("db.prepare('UPDATE product SET stock = stock - 1 WHERE id = ?')")
3925
+ && T("db.exec('BEGIN IMMEDIATE')") && T("INSERT INTO orders(x) VALUES(?)") && T("ON CONFLICT(idem_key) DO NOTHING");
3926
+ // FP 0: database/select/from/where 가 산문에 흩어져 있어도 단일 키워드·부분조합은 안 켠다
3927
+ const noFp = !T('// connect to the database and select from the menu')
3928
+ && !T('const total = items.reduce((a,b)=>a+b,0)')
3929
+ && !T('return items.filter(x => x.from && x.where)')
3930
+ && !T('updateProfile(user) // app update, no SQL');
3931
+ // 병합: database 우선 노출 + 최대 2 캡
3932
+ const mergeOk = eq(W(['code']), ['database', 'code']) && eq(W(['code', 'design']), ['database', 'code']) && eq(W([]), ['database']);
3933
+ return hit && noFp && mergeOk;
3934
+ } },
3935
+ { name: 'DB 렌즈 recall 보안·특례 (codex FN검수 P2/P3, 1.36.4): _anyDbContentInFiles root 제한 + 테스트파일 제외 (행위)', run: () => {
3936
+ const os = require('os');
3937
+ const parent = fs.mkdtempSync(path.join(os.tmpdir(), 'lz-dbc-'));
3938
+ const dir = path.join(parent, 'proj'); fs.mkdirSync(dir);
3939
+ try {
3940
+ const sql = "import { DatabaseSync } from 'node:sqlite'\ndb.prepare('SELECT * FROM t WHERE id=?')\n";
3941
+ fs.writeFileSync(path.join(dir, 'svc.mjs'), sql);
3942
+ fs.writeFileSync(path.join(dir, 'svc.test.mjs'), sql); // 테스트 파일(동일 DB 내용)
3943
+ fs.writeFileSync(path.join(parent, 'outside.mjs'), sql); // root 밖(존재+DB내용)
3944
+ const plain = _anyDbContentInFiles(['svc.mjs'], dir) === true;
3945
+ const testExcluded = _anyDbContentInFiles(['svc.test.mjs'], dir) === false; // codex P3: 테스트 제외
3946
+ const traversalBlocked = _anyDbContentInFiles(['../outside.mjs'], dir) === false // codex P2: ../ 거부
3947
+ && _anyDbContentInFiles([path.join(parent, 'outside.mjs')], dir) === false; // 절대경로 거부
3948
+ return plain && testExcluded && traversalBlocked;
3949
+ } finally { try { fs.rmSync(parent, { recursive: true, force: true }); } catch { /* ignore */ } }
3950
+ } },
3917
3951
  { name: 'GPT-5.5 평가 #5 (1.19.1, UR-0009) + 정직성 calibration (1.35.12): 클린룸 문서 공개 + 한계 명시 + self-administered 라벨 (행위)', run: () => {
3918
3952
  const dp = path.join(path.dirname(__filename), '..', 'docs', 'clean-room-evaluations.md');
3919
3953
  if (!exists(dp)) return true; // 패키지에 없으면 스킵(설치본 안전)
@@ -3921,6 +3955,16 @@ function _selfTestCases() {
3921
3955
  // 1.35.12: 정직성 마커 강화 — clean-room 프레이밍 + heuristic 한계 + self-administered(독립 아님) + 재현 레시피.
3922
3956
  return /clean-room/i.test(d) && /heuristic, not semantic/i.test(d) && /self-administered/i.test(d) && /npm i leerness@/.test(d);
3923
3957
  } },
3958
+ { name: '정직성 감사 (1.36.5, 심층감사 채택): capability matrix 성숙도 판정 휴리스틱 캐비엇 + 하드코딩%/완결성 과장 제거 (소스 가드)', run: () => {
3959
+ const hp = path.join(path.dirname(__filename), '..', 'lib', 'health.js');
3960
+ const h = exists(hp) ? read(hp) : '';
3961
+ if (!h) return true; // 설치본에 lib 없으면 스킵(안전)
3962
+ const caveatOk = /휴리스틱 자가평가/.test(h) && /heuristic self-assessment/i.test(h); // production-ready 판정 정직화
3963
+ const noCrudComplete = !/CRUD complete/i.test(h); // 도구수→기능완결성 과장 제거
3964
+ const fabricated = '72% ' + 'production-ready'; // split-literal: self-ref 트랩 회피
3965
+ const noHardcodedMaturity = !read(__filename).includes(fabricated); // REPL 하드코딩 성숙도% 제거
3966
+ return caveatOk && noCrudComplete && noHardcodedMaturity;
3967
+ } },
3924
3968
  { name: 'CLI 영어화 Phase 1 (1.20.2, UR-0010): _uiLang 해석(flag>env>manifest>ko) + 첫화면 _t 적용 (행위+소스)', run: () => {
3925
3969
  const save = process.argv; const saveEnv = process.env.LEERNESS_LANG;
3926
3970
  try {
@@ -4833,6 +4877,44 @@ function _lensDomainsForFiles(files) {
4833
4877
  const ordered = ['database', 'code', 'design', 'docs', 'test'].filter(d => out.includes(d));
4834
4878
  return ordered.slice(0, 2);
4835
4879
  }
4880
+ // 1.36.x (dogfood FN): path 휴리스틱은 관습적 이름(models/·.repository.·.sql 등)만 잡아, 평범한 이름의 DB 모듈
4881
+ // (inventory.safe.mjs · orders.occ.mjs 처럼 DB 를 다루지만 이름에 단서 없음)을 놓친다. 내용 기반으로 보강한다:
4882
+ // claimed 파일이 실제 DB 드라이버를 import 하거나 산문엔 안 나오는 명백한 SQL DDL/트랜잭션 토큰을 담으면 database 렌즈를 켠다.
4883
+ // FP 가드: "database" 라는 단어만으로는 안 켠다 — 드라이버 import 또는 CREATE TABLE/INSERT INTO/ON CONFLICT/BEGIN IMMEDIATE/FOR UPDATE 급 토큰이 있어야 함.
4884
+ const _DB_IMPORT_RE = /(?:require\s*\(|\bfrom|\bimport)\s*['"](?:node:sqlite|better-sqlite3|sqlite3|pg|postgres|mysql2?|knex|typeorm|sequelize|drizzle-orm|@prisma\/client|mongodb|mongoose|ioredis|redis|oracledb|tedious|@libsql\/client)['"]/i;
4885
+ // 단일 SQL 키워드는 산문 FP 위험(select/update/from/where 는 영어 단어) → 산문에 거의 없는 조합만: DDL/트랜잭션 토큰 또는
4886
+ // 완결형 문장 패턴(SELECT…FROM…WHERE / UPDATE…SET…WHERE / DELETE FROM…WHERE). 근접 조합이라 산문 FP 가 급감한다.
4887
+ const _DB_SQL_RE = /\b(?:CREATE\s+TABLE|INSERT\s+INTO|ON\s+CONFLICT|BEGIN\s+(?:IMMEDIATE|TRANSACTION|DEFERRED|EXCLUSIVE)|FOR\s+UPDATE)\b|\bSELECT\b[\s\S]{0,120}?\bFROM\b[\s\S]{0,120}?\bWHERE\b|\bUPDATE\b[\s\S]{0,80}?\bSET\b[\s\S]{0,200}?\bWHERE\b|\bDELETE\s+FROM\b[\s\S]{0,120}?\bWHERE\b/i;
4888
+ function _isDbContentText(txt) {
4889
+ return typeof txt === 'string' && (_DB_IMPORT_RE.test(txt) || _DB_SQL_RE.test(txt));
4890
+ }
4891
+ // claimed 파일 중 코드 파일을 읽어 DB 내용 신호가 있으면 true. 미존재/큰 파일(>512KB)은 건너뜀(안전·비용).
4892
+ // 보안(codex P2): 경로는 root 안으로 제한 — 절대경로/../ 트래버설로 워크스페이스 밖 파일을 읽지 않는다. 심볼릭 링크는 스킵.
4893
+ // codex P3: 테스트 파일은 DB 증강에서 제외 — test 렌즈를 축출하지 않도록(_lensDomainsForFiles 의 test 특례와 일관).
4894
+ function _anyDbContentInFiles(files, root) {
4895
+ const arr = Array.isArray(files) ? files : [];
4896
+ const base = path.resolve(root || process.cwd());
4897
+ const _testRe = /(^|[\\/])(test_[^\\/]+\.[a-z]+|[^\\/]+[._-]test\.[a-z]+|[^\\/]+\.spec\.[a-z]+)$|(^|[\\/])tests?[\\/]/i;
4898
+ for (const f of arr) {
4899
+ if (typeof f !== 'string') continue;
4900
+ if (!/\.(js|mjs|cjs|ts|tsx|py|rb|go|rs|java|cs|php)$/i.test(f)) continue;
4901
+ if (_testRe.test(f)) continue; // 테스트 파일 → test 렌즈 유지(DB 증강 제외)
4902
+ try {
4903
+ const p = path.resolve(base, f);
4904
+ if (p !== base && !p.startsWith(base + path.sep)) continue; // root 밖(../·절대경로) 거부
4905
+ const st = fs.lstatSync(p); // 심볼릭 링크는 따라가지 않음(isFile()=false → 스킵)
4906
+ if (!st.isFile() || st.size > 512 * 1024) continue;
4907
+ if (_isDbContentText(fs.readFileSync(p, 'utf8'))) return true;
4908
+ } catch { /* 미존재/권한 → 무시 */ }
4909
+ }
4910
+ return false;
4911
+ }
4912
+ // database 를 도메인 목록에 병합(우선 노출 + 최대 2 캡). database 가 code/design 등보다 앞선다.
4913
+ function _withDbDomain(domains) {
4914
+ const merged = Array.isArray(domains) ? domains.slice() : [];
4915
+ if (!merged.includes('database')) merged.unshift('database');
4916
+ return ['database', 'code', 'design', 'docs', 'test'].filter(d => merged.includes(d)).slice(0, 2);
4917
+ }
4836
4918
  function lensCmd(domain, opts = {}) {
4837
4919
  const jsonMode = !!opts.json || has('--json');
4838
4920
  // 1.19.1 (19th 버그헌트): 도메인 인자 정규화 — `lens Code` / `lens CODE ` 도 인식(대소문자·공백 무관).
@@ -11072,7 +11154,9 @@ function verifyClaimCmd(root, taskId, opts = {}) {
11072
11154
  log(t(` ℹ 한계: 테스트 통과는 "의미적 구현 정확성"을 보장하지 않음 — evidence 가 해당 주장(수정 파일/테스트)을 직접 링크해야 신뢰도↑.`, ` ℹ Limit: passing tests do not guarantee "semantic correctness" — evidence should directly link the claimed files/tests for higher confidence.`));
11073
11155
  // 1.19.2 (UR-0003 렌즈 완전판 v2): 완료-검증 순간에 분야별 자기질문 advisory — 주장 파일 확장자 기반(결정적).
11074
11156
  // 기계검증(파일/테스트/스텁)을 통과해도 "사람이 보기에 좋은가"는 별개 → AI 가 스스로 답하도록 권장(advisory, 게이트 아님).
11075
- const _lensDoms = _lensDomainsForFiles(files);
11157
+ let _lensDoms = _lensDomainsForFiles(files);
11158
+ // 1.36.x (dogfood FN): path 가 놓친 평범한 이름의 DB 모듈 — claimed 파일 내용에 DB 신호가 있으면 database 렌즈 보강.
11159
+ if (!_lensDoms.includes('database') && _anyDbContentInFiles(files, root)) _lensDoms = _withDbDomain(_lensDoms);
11076
11160
  if (_lensDoms.length) {
11077
11161
  const _lensCat = _effectiveLensCatalog(root); // 1.19.3: 프로젝트 커스텀 질문도 포함
11078
11162
  log('');
@@ -18582,7 +18666,7 @@ async function _agentRepl(root, opts) {
18582
18666
  log(C.green(' │ ') + C.dim('• Bridge slash :web/:pc/:lsp REPL 즉시 호출 + LSP 다국어 5종') + C.green(' │'));
18583
18667
  log(C.green(' │ ') + C.dim('• review-request 사전 검토 + task add 자동 trigger') + C.green(' │'));
18584
18668
  log(C.green(' │ ') + C.dim('• release sync-main 자동 npm publish (.env NPM_TOKEN)') + C.green(' │'));
18585
- log(C.green(' │ ') + C.dim('• 6 능력 매트릭스 72% production-ready · MCP 54 도구') + C.green(' │'));
18669
+ log(C.green(' │ ') + C.dim('• 6 능력 매트릭스 자가평가 (leerness health 상세)') + C.green(' │'));
18586
18670
  log(C.bold(C.green(' └─────────────────────────────────────────────────────────────────────┘')));
18587
18671
  log('');
18588
18672
  log(C.bold(' Available Slash (5 그룹)'));
@@ -21087,5 +21171,6 @@ module.exports = {
21087
21171
  // 1.18.2: verify-claim 위장 스텁(빈 export 껍데기) 판정 — 단위 테스트
21088
21172
  _vcImplIsEmpty, _VC_EMPTY_SHELL_RE,
21089
21173
  // 1.18.3 (UR-0003): 분야별 자기질문 품질 렌즈 — 단위 테스트. 1.19.2: 파일→도메인 매핑(완료-검증 advisory)
21090
- LENS_CATALOG, lensCmd, _lensDomainsForFiles, _mergeLensCatalog, _loadProjectLenses, _effectiveLensCatalog
21174
+ LENS_CATALOG, lensCmd, _lensDomainsForFiles, _mergeLensCatalog, _loadProjectLenses, _effectiveLensCatalog,
21175
+ _isDbContentText, _anyDbContentInFiles, _withDbDomain
21091
21176
  };
package/lib/health.js CHANGED
@@ -270,7 +270,7 @@ function healthCmd(root, deps = {}) {
270
270
  // (5) MCP 도구 — tools array 카운트 (1.9.288: 정확한 도구 정의 패턴 — 자기-매칭 오탐 제거, Codex #5)
271
271
  const toolCount = _mcpToolCount();
272
272
  cap.mcpTools = toolCount >= 50
273
- ? { score: 100, status: '✓', evidence: t(`${toolCount}/50+ 도구 (1.9.159 CRUD 완성)`, `${toolCount}/50+ tools (CRUD complete)`) }
273
+ ? { score: 100, status: '✓', evidence: t(`${toolCount}/50+ 도구`, `${toolCount}/50+ tools`) }
274
274
  : { score: Math.round((toolCount / 50) * 100), status: toolCount > 30 ? '✓' : '⚠', evidence: t(`${toolCount} 도구`, `${toolCount} tools`) };
275
275
  // (6) 코드 인텔리전스 — 1.9.167 LSP 어댑터 + typescript 설치 detect
276
276
  const hasLspBridge = /function lspCmd\(root, sub/.test(harnessSrc);
@@ -350,6 +350,8 @@ function healthCmd(root, deps = {}) {
350
350
  log(t(`## 🧪 6능력 매트릭스 (1.9.167 자동 평가)`, `## 🧪 6-capability matrix (auto-assessed)`));
351
351
  const cm = out.capabilityMatrix;
352
352
  log(t(` 종합: ${cm.overallScore}% (${cm.assessment})`, ` overall: ${cm.overallScore}% (${cm.assessment})`));
353
+ // 1.36.5 (정직성 감사): 이 점수/판정은 소스 존재·의존성 휴리스틱 자가평가일 뿐 — 측정된/독립 성숙도 검증이 아님을 명시(과장 방지).
354
+ log(t(` ⚠ 소스 존재·의존성 기반 휴리스틱 자가평가 — 측정된/독립 성숙도 판정 아님(미설치 의존성도 부분점수).`, ` ⚠ heuristic self-assessment from source-presence + dependency checks — NOT a measured or independent maturity verdict (a missing dependency still scores partial).`));
353
355
  log(t(` (1) 웹 자동화 ${cm.capabilities.webAutomation.status} ${cm.capabilities.webAutomation.score}% · ${cm.capabilities.webAutomation.evidence}`, ` (1) web automation ${cm.capabilities.webAutomation.status} ${cm.capabilities.webAutomation.score}% · ${cm.capabilities.webAutomation.evidence}`));
354
356
  log(t(` (2) PC 조작 ${cm.capabilities.pcAutomation.status} ${cm.capabilities.pcAutomation.score}% · ${cm.capabilities.pcAutomation.evidence}`, ` (2) PC control ${cm.capabilities.pcAutomation.status} ${cm.capabilities.pcAutomation.score}% · ${cm.capabilities.pcAutomation.evidence}`));
355
357
  log(t(` (3) 멀티 오케스트레이션 ${cm.capabilities.multiAgentOrchestration.status} ${cm.capabilities.multiAgentOrchestration.score}% · ${cm.capabilities.multiAgentOrchestration.evidence}`, ` (3) multi-agent orch. ${cm.capabilities.multiAgentOrchestration.status} ${cm.capabilities.multiAgentOrchestration.score}% · ${cm.capabilities.multiAgentOrchestration.evidence}`));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "leerness",
3
- "version": "1.36.3",
3
+ "version": "1.36.5",
4
4
  "description": "Leerness: 비파괴 마이그레이션, 자동 버전 감지·업데이트, 계획/진행/핸드오프 자동화, 게으름·시크릿·인코딩 자동 가드, Claude Code 슬래시 통합을 갖춘 한국어 우선 AI 개발 하네스.",
5
5
  "keywords": [
6
6
  "leerness",