leerness 1.36.5 → 1.36.7

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,23 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.36.7 — 2026-07-09 — handoff 넛지: 세션-시작 리추얼 사각지대 메꿈 (메타-테스트 도그푸드)
4
+
5
+ **자기 행동 실측(세션 트랜스크립트 파싱)에서 드러난 사각지대를 leerness 기능으로 메꿈.** "세션이 길수록 leerness를 덜 참조하는가?" 가설을 트랜스크립트로 측정 → **반박**(workspace 사용은 세션 길이가 아니라 작업 종류에 종속). 단 실재 gap 1건: **compaction/resume 직후 세션-시작 `leerness handoff`를 건너뜀**(요약이 "resume mid-task"를 지시). 그 신호는 handoff 출력에만 떴는데 정작 handoff 를 안 돌리는 게 문제.
6
+
7
+ - 신규: `_handoffNudgeState`/`_emitHandoffNudge` — `task add`/`decision add`(에이전트가 작업 중 실제로 실행하는 명령) 시, 마지막 handoff 가 오래됨(gap > 120분)이면 **한 줄 넛지**: `⚠ 마지막 handoff N시간 전 — 'leerness handoff .' 권장`.
8
+ - FP 가드: **기록 있음 + gap > 임계**일 때만(신규 프로젝트=last-handoff.json 부재 → 넛지 안 함). `--json`/`--quiet` 오염 없음. opt-out `LEERNESS_NO_HANDOFF_NUDGE=1`.
9
+ - 정본 `_getLastHandoffGap` 재사용(스키마 일관). selftest 281(행위: 오래됨→넛지·최근/부재→없음·opt-out) + e2e 통과.
10
+
11
+ ## 1.36.6 — 2026-07-09 — 정직성 백로그 소진: 강제력/종합-health 문구 정직화 (심층 감사 P2/P3 후속)
12
+
13
+ **1.36.5 심층 정직성 감사가 확인했으나 미수정으로 남긴 P2/P3 강제력·과장 문구를 정직화.**
14
+
15
+ - **handoff `⚕ health` 토큰 → `🔐 .env`**: 이 헤드라인 토큰은 실제로 **.env 의 .gitignore 보호 여부만** 봤는데 "종합 health(보안+drift)"로 표기했다(주석까지 그렇게 거짓). 커밋된 시크릿/drift/상태무결성은 안 봄 → 라벨을 `🔐 .env` 로 정직화(종합 health 아님 명시).
16
+ - **policy enforce "초과 명령 차단"** → `초과 명령 = 차단 판정 + exit 1 신호 · 실제 셸 실행을 가로채진 않음`: leerness 는 셸을 감싸지 않으므로 enforce ON 이어도 협조적 verdict/exit code 일 뿐, 하드 실행 차단이 아님을 명시.
17
+ - **KO identity/about "허위 완료 차단" → "허위 완료 감지 (권고; CI 게이트 필수화 시 차단)"**: EN 설명은 이미 협조적(권고)임을 밝히는데 KO 정체성/about/README 는 하드 "차단"으로 과장 → EN 과 일치시킴(사용자 프로젝트 README 에 기록되는 고가시성 문구).
18
+ - **README "measures the real count and rejects a mismatch"** → 기본은 **테스트 선언(정적 카운트)** 이 주장 초과 시 거부하는 것이지 "통과" 증명이 아님을 명시(+`--run-tests` 로 실제 실행 검증).
19
+ - selftest 280 (신규 정직성 후속 소스가드, split-literal self-ref 회피) + e2e 통과.
20
+
3
21
  ## 1.36.5 — 2026-07-09 — 정직성 감사: 성숙도 판정 과장 보정 (심층 멀티에이전트 정직성 감사 채택)
4
22
 
5
23
  **게시본 1.36.4에 9개 사용자대면 표면 정직성 감사(멀티에이전트 35 + 적대적 반증) → 가장 강하게 수렴한 P1(성숙도 판정 과장) 보정.**
package/README.md CHANGED
@@ -35,7 +35,7 @@ npx leerness verify-claim T-0002 # exit 1 — payment.js does not exist. Claim
35
35
 
36
36
  Now actually write `payment.js`, then run the **same** `verify-claim T-0002` → it exits 0. That is the whole idea: **"done" must match reality.**
37
37
 
38
- > Tip: if your evidence claims a specific test count (e.g. "5 tests passed"), leerness measures the real count and rejects a mismatch — so claim only what's true, or add `--run-tests --test-cmd "<your test cmd>"` to verify by running them.
38
+ > Tip: if your evidence claims a specific test count (e.g. "5 tests passed"), leerness counts the test functions actually present and rejects a claim that exceeds them — so claim only what's true. That default is a static count of test declarations, not proof they pass; add `--run-tests --test-cmd "<your test cmd>"` to verify they actually pass by running them.
39
39
 
40
40
  > Want a smaller footprint? `leerness init . --minimal` installs only the core memory + verification files instead of the full set.
41
41
 
@@ -125,7 +125,7 @@ MIT
125
125
  <!-- leerness:project-readme:start -->
126
126
  ## Leerness Project Harness
127
127
 
128
- 이 프로젝트는 Leerness v1.36.5 하네스를 사용합니다. AI 에이전트는 작업 전 `leerness handoff`로 컨텍스트를 적재하고, 작업 후 `leerness check`/`leerness audit`/`leerness session close`를 수행해야 합니다.
128
+ 이 프로젝트는 Leerness v1.36.7 하네스를 사용합니다. AI 에이전트는 작업 전 `leerness handoff`로 컨텍스트를 적재하고, 작업 후 `leerness check`/`leerness audit`/`leerness session close`를 수행해야 합니다.
129
129
 
130
130
  ### 정체성 — AI 에이전트 운영 레이어 (UR-0030)
131
131
 
@@ -134,7 +134,7 @@ Leerness 는 **실행기/코딩 에이전트가 아니라**, 어떤 AI 코딩
134
134
  - **기억(Memory)** — 프로젝트 상태/결정/진행을 `.harness/` 에 영속화
135
135
  - **정책(Policy)** — 8단계 권한 등급 + enforce (read-only→publish), MCP 호출 게이트
136
136
  - **인수인계(Handoff)** — 에이전트 간 컨텍스트 표준 전달 + `get_project_context` 1콜 온보딩
137
- - **검증(Verification)** — 근거 기반 완료 검증으로 허위 완료 차단
137
+ - **검증(Verification)** — 근거 기반 완료 검증으로 허위 완료 감지 (권고; CI 게이트 필수화 시 차단)
138
138
  - **감사(Audit)** — drift/idempotency/secret/encoding 자동 감사 + self-heal
139
139
 
140
140
  AGENTS.md(정적 지침)을 **대체하지 않고 보완**합니다 — 정적 규칙은 AGENTS.md, 동적 상태·검증·인수인계는 leerness. 정체성 조회: `leerness about` (MCP `leerness_about`).
@@ -179,7 +179,7 @@ leerness memory restore decision <date|title>
179
179
 
180
180
  ### MCP server (외부 AI 통합)
181
181
 
182
- Leerness v1.36.5는 stdio JSON-RPC MCP server를 내장합니다 — Claude Code · Cursor · Codex CLI 등 외부 AI에 **86개 도구**를 노출:
182
+ Leerness v1.36.7는 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.5는 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.5)** · 매 라운드 GitHub release/태그 생성 · _reports/는 비공개 보존.
203
+ 현재 누적: **70 라운드 (1.9.40 → 1.36.7)** · 매 라운드 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.5: 2026-07-09
241
+ Last synced by Leerness v1.36.7: 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.5';
36
+ const VERSION = '1.36.7';
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') 시 호스트 프로세스 오염.
@@ -301,7 +301,7 @@ function managedReadmeBlock(project) {
301
301
  '- **기억(Memory)** — 프로젝트 상태/결정/진행을 `.harness/` 에 영속화',
302
302
  '- **정책(Policy)** — 8단계 권한 등급 + enforce (read-only→publish), MCP 호출 게이트',
303
303
  '- **인수인계(Handoff)** — 에이전트 간 컨텍스트 표준 전달 + `get_project_context` 1콜 온보딩',
304
- '- **검증(Verification)** — 근거 기반 완료 검증으로 허위 완료 차단',
304
+ '- **검증(Verification)** — 근거 기반 완료 검증으로 허위 완료 감지 (권고; CI 게이트 필수화 시 차단)',
305
305
  '- **감사(Audit)** — drift/idempotency/secret/encoding 자동 감사 + self-heal',
306
306
  '',
307
307
  'AGENTS.md(정적 지침)을 **대체하지 않고 보완**합니다 — 정적 규칙은 AGENTS.md, 동적 상태·검증·인수인계는 leerness. 정체성 조회: `leerness about` (MCP `leerness_about`).',
@@ -3965,6 +3965,34 @@ function _selfTestCases() {
3965
3965
  const noHardcodedMaturity = !read(__filename).includes(fabricated); // REPL 하드코딩 성숙도% 제거
3966
3966
  return caveatOk && noCrudComplete && noHardcodedMaturity;
3967
3967
  } },
3968
+ { name: '정직성 감사 후속 (1.36.6, 백로그 소진): handoff .env 토큰 + KO identity/policy 강제력 문구 정직화 (소스 가드)', run: () => {
3969
+ const self = read(__filename);
3970
+ const oldHealthTok = '⚕ ' + 'health:'; // split-literal(escape+concat): 옛 종합-health 토큰 라벨 self-ref 회피
3971
+ const tokenHonest = self.includes('🔐 .env:') && !self.includes(oldHealthTok); // handoff 토큰: 종합 health 오칭 → .env 보호로 정직화
3972
+ const idHonest = self.includes('허위 완료 감지 (권고'); // KO identity/about: 차단(하드) → 감지(권고; CI 시 차단)
3973
+ const policyHonest = self.includes('실제 셸 실행을 가로채진 않음'); // policy enforce: 차단 판정이 실행 가로채기 아님을 명시
3974
+ return tokenHonest && idHonest && policyHonest;
3975
+ } },
3976
+ { name: 'handoff 넛지 (1.36.7, 메타-테스트 도그푸드): 오래된 handoff→넛지 · 최근/부재→없음 · opt-out 존중 (행위)', run: () => {
3977
+ const os = require('os');
3978
+ const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'lz-hn-'));
3979
+ const hd = path.join(dir, '.harness'); fs.mkdirSync(hd);
3980
+ const lhf = path.join(hd, 'last-handoff.json');
3981
+ const iso = (msAgo) => new Date(Date.now() - msAgo).toISOString();
3982
+ try {
3983
+ const noneOk = _handoffNudgeState(dir) === null; // 부재 → 넛지 없음(신규 프로젝트 FP 방지)
3984
+ fs.writeFileSync(lhf, JSON.stringify({ last: iso(3 * 3600 * 1000), history: [iso(3 * 3600 * 1000)] }));
3985
+ const st = _handoffNudgeState(dir);
3986
+ const staleOk = !!st && st.gapMin >= 120; // 3h 오래됨 → 넛지
3987
+ fs.writeFileSync(lhf, JSON.stringify({ last: iso(5 * 60 * 1000), history: [iso(5 * 60 * 1000)] }));
3988
+ const freshOk = _handoffNudgeState(dir) === null; // 5min 최근 → 없음
3989
+ process.env.LEERNESS_NO_HANDOFF_NUDGE = '1';
3990
+ fs.writeFileSync(lhf, JSON.stringify({ last: iso(3 * 3600 * 1000), history: [] }));
3991
+ const optOutOk = _handoffNudgeState(dir) === null; // opt-out 존중
3992
+ delete process.env.LEERNESS_NO_HANDOFF_NUDGE;
3993
+ return noneOk && staleOk && freshOk && optOutOk;
3994
+ } finally { try { fs.rmSync(dir, { recursive: true, force: true }); } catch { /* ignore */ } }
3995
+ } },
3968
3996
  { name: 'CLI 영어화 Phase 1 (1.20.2, UR-0010): _uiLang 해석(flag>env>manifest>ko) + 첫화면 _t 적용 (행위+소스)', run: () => {
3969
3997
  const save = process.argv; const saveEnv = process.env.LEERNESS_LANG;
3970
3998
  try {
@@ -6992,6 +7020,29 @@ function _getLastHandoffGap(root) {
6992
7020
  return { hasLast: true, lastAt: j.last, gapMin, expected, isMiss, isLong, history: j.history || [] };
6993
7021
  } catch { return { hasLast: false }; }
6994
7022
  }
7023
+ // 1.36.7 (메타-테스트 도그푸드): 세션에서 작업 중(task/decision add)인데 handoff 가 오래됨/미실행이면 넛지.
7024
+ // 실측(트랜스크립트)에서 확인된 사각지대: compaction/resume 후 세션-시작 handoff 리추얼을 건너뜀 → 컨텍스트 미적재.
7025
+ // 그 신호는 handoff 출력에만 떴는데 정작 handoff 를 안 돌리는 게 문제라, 에이전트가 실제로 실행하는 명령에 넛지를 노출.
7026
+ // FP 가드: 기록 있음 + gap > 임계(기본 120분)일 때만(신규 프로젝트=기록 없음 → 넛지 안 함). opt-out: LEERNESS_NO_HANDOFF_NUDGE=1.
7027
+ const HANDOFF_NUDGE_MIN = 120;
7028
+ function _handoffNudgeState(root, thresholdMin = HANDOFF_NUDGE_MIN) {
7029
+ if (process.env.LEERNESS_NO_HANDOFF_NUDGE === '1') return null;
7030
+ try {
7031
+ const g = _getLastHandoffGap(root);
7032
+ if (g && g.hasLast && g.gapMin > thresholdMin) return { gapMin: g.gapMin };
7033
+ } catch {}
7034
+ return null;
7035
+ }
7036
+ function _emitHandoffNudge(root) {
7037
+ if (has('--json') || has('--quiet')) return; // 구조화/조용 모드 오염 방지
7038
+ const s = _handoffNudgeState(root);
7039
+ if (!s) return;
7040
+ const L = _uiLang(root); const tt = (ko, en) => (L === 'en' ? en : ko);
7041
+ const koAge = s.gapMin < 120 ? `${s.gapMin}분` : `${Math.floor(s.gapMin / 60)}시간`;
7042
+ const enAge = s.gapMin < 120 ? `${s.gapMin}min` : `${Math.floor(s.gapMin / 60)}h`;
7043
+ log(tt(` ⚠ 마지막 handoff ${koAge} 전 — 이 세션 컨텍스트 최신화를 위해 'leerness handoff .' 권장 (끄기: LEERNESS_NO_HANDOFF_NUDGE=1)`,
7044
+ ` ⚠ last handoff ${enAge} ago — run 'leerness handoff .' to refresh this session's context (off: LEERNESS_NO_HANDOFF_NUDGE=1)`));
7045
+ }
6995
7046
 
6996
7047
  // 1.9.198: B축 (멀티 Sub-Agent 오케스트라) 보강 — handoff 에서 task keyword 매칭 best agent 추천
6997
7048
  // 1.9.193 에서 agents multi --execute 결과를 lessons.md 에 기록 → 이를 keyword 매칭하여 추출
@@ -7693,6 +7744,7 @@ function taskAdd(root, text) {
7693
7744
  if (has('--json')) { log(JSON.stringify({ ok: true, id, status: _normTaskStatus(arg('--status', 'requested')), request: text })); return; }
7694
7745
  ok(`task added: ${id}`);
7695
7746
  _autoRoadmap(absRoot(root), 'data-change');
7747
+ _emitHandoffNudge(root); // 1.36.7: 세션 handoff 미실행/오래됨 넛지 (compaction/resume 사각지대)
7696
7748
  // 1.9.177: task add 자동 review-request trigger (사용자 명시 1.9.176 자동화).
7697
7749
  // 사용자가 task 추가 시 자동으로 사전 검토 — 충돌/재사용/효율/권장 단계 결과를 등록 직후 표시.
7698
7750
  // opt-out: --no-review 또는 env LEERNESS_NO_AUTO_REVIEW=1, 또는 status=in-progress/done 같은 운영 메타.
@@ -8184,6 +8236,7 @@ function decisionAdd(root, title) {
8184
8236
  ok(`decision added: ${title}`);
8185
8237
  // 1.9.43+ handoff lessons 회수 흐름과 자동 통합 (decisions.md fuzzy 매칭됨)
8186
8238
  _autoRoadmap(absRoot(root), 'data-change');
8239
+ _emitHandoffNudge(root); // 1.36.7: 세션 handoff 미실행/오래됨 넛지 (compaction/resume 사각지대)
8187
8240
  }
8188
8241
 
8189
8242
  // 1.9.6: 옛 link 손실 row를 plan.md milestone과 자동 매칭 제안/복구.
@@ -9109,19 +9162,17 @@ function handoff(root) {
9109
9162
  const skillCnt = Object.keys(all).length;
9110
9163
  if (skillCnt > 0) parts.push(`📚 ${skillCnt} skills`);
9111
9164
  } catch {}
9112
- // 6) 1.9.93: health 종합 (보안 + drift 결합 1 토큰)
9113
- // 헤드라인의 다른 신호는 이미 계산됨 inline 추론 (자식 spawn 없음)
9165
+ // 6) 1.9.93 1.36.6 정직화: 토큰은 .env gitignore 보호 여부만 본다 — 종합 health 가 아니다
9166
+ // (커밋된 시크릿/drift/상태무결성은 `leerness health`/`scan secrets`/`drift check` 확인). 라벨을 '🔐 .env' 로 정직화.
9114
9167
  try {
9115
- // 보안 위험 ↔ healthy 판정 (간단)
9116
9168
  const envPath = path.join(root, '.env');
9117
- let healthIssue = false;
9169
+ let envUnprotected = false;
9118
9170
  if (exists(envPath)) {
9119
9171
  const giText = exists(path.join(root, '.gitignore')) ? read(path.join(root, '.gitignore')) : '';
9120
9172
  const giLines = giText.split('\n').map(l => l.trim());
9121
- if (!(giLines.includes('.env') || giLines.includes('/.env'))) healthIssue = true;
9173
+ if (!(giLines.includes('.env') || giLines.includes('/.env'))) envUnprotected = true;
9122
9174
  }
9123
- // 헤드라인 끝에 health 토큰
9124
- parts.push(healthIssue ? '⚕ health: ⚠' : '⚕ health: ✓');
9175
+ parts.push(envUnprotected ? '🔐 .env: ⚠' : '🔐 .env: ✓'); // .env 보호만 — 종합 health 아님
9125
9176
  } catch {}
9126
9177
  // 7) 1.9.113: Memory Write Surface 5종 카운트 (T=tasks in-progress / D=decisions / R=rules active / P=plan milestones / L=lessons)
9127
9178
  try {
@@ -18024,7 +18075,7 @@ function policyCmd(root, sub, ...args) {
18024
18075
  if (json) { log(JSON.stringify({ tiers: PERMISSION_TIERS, allowedTier: p.allowedTier, enforce: p.enforce, powerfulCommands: POWERFUL_COMMANDS.map(c => ({ cmd: c.cmd, requiredTier: _requiredTier(c.cmd) })) }, null, 2)); return; }
18025
18076
  log(`# leerness policy (1.9.281, UR-0034) — 권한 등급`);
18026
18077
  log(`등급(위험 오름차순): ${PERMISSION_TIERS.join(' < ')}`);
18027
- log(`허용 등급: ${p.allowedTier} · enforce: ${p.enforce ? '🔴 ON (초과 명령 차단)' : '🟢 OFF (advisory only, 기본)'}`);
18078
+ log(`허용 등급: ${p.allowedTier} · enforce: ${p.enforce ? '🔴 ON (초과 명령 = 차단 판정 + exit 1 신호 · 실제 셸 실행을 가로채진 않음)' : '🟢 OFF (advisory only, 기본)'}`);
18028
18079
  log('');
18029
18080
  log(`## 주의 명령 요구 등급`);
18030
18081
  for (const c of POWERFUL_COMMANDS) { const rt = _requiredTier(c.cmd); const al = _policyAllows(p.allowedTier, rt); log(` ${al ? '🟢' : (p.enforce ? '🔴' : '🟡')} ${c.cmd.padEnd(22)} → ${rt}`); }
@@ -18087,7 +18138,7 @@ function _leernessIdentity() {
18087
18138
  { key: 'memory', ko: '기억', desc: '프로젝트 상태/결정/진행을 .harness/ 에 영속화 (task/decision/lesson/plan; 선택 state substrate 는 .leerness/)' },
18088
18139
  { key: 'policy', ko: '정책', desc: '8단계 권한 등급 + enforce (read-only→publish), MCP 호출 게이트' },
18089
18140
  { key: 'handoff', ko: '인수인계', desc: '에이전트 간 컨텍스트 표준 전달 (Claude→Codex→Goose), get_project_context 1콜 온보딩' },
18090
- { key: 'verification', ko: '검증', desc: '근거 기반 완료 검증 (verify-claim --require-evidence) — 허위 완료 차단' },
18141
+ { key: 'verification', ko: '검증', desc: '근거 기반 완료 검증 (verify-claim --require-evidence) — 허위 완료 감지 (권고; CI 게이트 시 차단)' },
18091
18142
  { key: 'audit', ko: '감사', desc: 'drift/idempotency/secret/encoding 자동 감사 + self-heal (--auto-fix)' }
18092
18143
  ],
18093
18144
  complements: 'AGENTS.md(정적 지침)을 대체하지 않고 보완 — 정적 규칙/명령/금지는 AGENTS.md, 동적 상태·기억·검증·인수인계는 leerness',
@@ -21172,5 +21223,6 @@ module.exports = {
21172
21223
  _vcImplIsEmpty, _VC_EMPTY_SHELL_RE,
21173
21224
  // 1.18.3 (UR-0003): 분야별 자기질문 품질 렌즈 — 단위 테스트. 1.19.2: 파일→도메인 매핑(완료-검증 advisory)
21174
21225
  LENS_CATALOG, lensCmd, _lensDomainsForFiles, _mergeLensCatalog, _loadProjectLenses, _effectiveLensCatalog,
21175
- _isDbContentText, _anyDbContentInFiles, _withDbDomain
21226
+ _isDbContentText, _anyDbContentInFiles, _withDbDomain,
21227
+ _handoffNudgeState, _getLastHandoffGap, _recordLastHandoff
21176
21228
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "leerness",
3
- "version": "1.36.5",
3
+ "version": "1.36.7",
4
4
  "description": "Leerness: 비파괴 마이그레이션, 자동 버전 감지·업데이트, 계획/진행/핸드오프 자동화, 게으름·시크릿·인코딩 자동 가드, Claude Code 슬래시 통합을 갖춘 한국어 우선 AI 개발 하네스.",
5
5
  "keywords": [
6
6
  "leerness",