leerness 1.36.67 → 1.36.68
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 +9 -0
- package/README.md +4 -4
- package/bin/leerness.js +1 -1
- package/lib/session-close.js +14 -1
- package/package.json +1 -1
- package/scripts/e2e.js +32 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.36.68 — 2026-07-22 — F14 재구현: 마감 보고의 미승인 미리보기 (8차 헌트 이연분 종결) — R-0001 검수 11회전
|
|
4
|
+
|
|
5
|
+
1.36.67 에서 이연했던 F14 를 원인 규명 후 재구현.
|
|
6
|
+
|
|
7
|
+
- **이연 원인(규명)**: 이전 삽입 지점이 `try/finally` 밖 **jsonMode 전용 후처리 구간**이라 텍스트 경로가 도달조차 못 했다(추정 아님 — 코드 구조 확인). 텍스트 렌더 구간으로 이동해 양 모드 동일 데이터 출력.
|
|
8
|
+
- **`session close` 가 승인 대기 미리보기를 보고**: 텍스트 블록(최대 5줄) + `pendingPreviews {count, items[≤10]}` JSON 필드. proposed/revision-requested 는 대기, approved 는 제외. 손상 previews.json 은 count 0 으로 안전 강등(마감 중단 없음 — 검수 확인).
|
|
9
|
+
- (검수 Medium) **`--no-suggest`/`LEERNESS_NO_SUGGEST=1` 에서도 노출**: suggest 블록 안에 있어 승인 대기 상태가 사라지던 것 — 공용 구간으로 이동 + e2e 회귀 가드.
|
|
10
|
+
- 검증: 텍스트/JSON 일치·JSON 순수성·12건 캡(텍스트 5·items 10)·en 렌더·승인 시 소거(검수 프로브), selftest 334, e2e +1.
|
|
11
|
+
|
|
3
12
|
## 1.36.67 — 2026-07-22 — tech 갱신 시 그래프 동반 정합 (8차 헌트 F15)
|
|
4
13
|
|
|
5
14
|
- **F15**: `leerness tech` 가 프로필 변경을 감지하면 이미 존재하는 `leerness.html` 의 🛠 탭도 함께 갱신 — 종전엔 프로필만 최신이고 그래프는 옛 서비스를 계속 보여줬다(다음 handoff 전까지 불일치). 그래프 산출물이 없는 프로젝트는 무동작(생성 강제 안 함).
|
package/README.md
CHANGED
|
@@ -122,7 +122,7 @@ MIT
|
|
|
122
122
|
<!-- leerness:project-readme:start -->
|
|
123
123
|
## Leerness Project Harness
|
|
124
124
|
|
|
125
|
-
이 프로젝트는 Leerness v1.36.
|
|
125
|
+
이 프로젝트는 Leerness v1.36.68 하네스를 사용합니다. AI 에이전트는 작업 전 `leerness handoff`로 컨텍스트를 적재하고, 작업 후 `leerness check`/`leerness audit`/`leerness session close`를 수행해야 합니다.
|
|
126
126
|
|
|
127
127
|
### 정체성 — AI 에이전트 운영 레이어 (UR-0030)
|
|
128
128
|
|
|
@@ -176,7 +176,7 @@ leerness memory restore decision <date|title>
|
|
|
176
176
|
|
|
177
177
|
### MCP server (외부 AI 통합)
|
|
178
178
|
|
|
179
|
-
Leerness v1.36.
|
|
179
|
+
Leerness v1.36.68는 stdio JSON-RPC MCP server를 내장합니다 — Claude Code · Cursor · Codex CLI 등 외부 AI에 **86개 도구**를 노출:
|
|
180
180
|
|
|
181
181
|
```jsonc
|
|
182
182
|
// 카테고리별
|
|
@@ -197,7 +197,7 @@ Leerness v1.36.67는 stdio JSON-RPC MCP server를 내장합니다 — Claude Cod
|
|
|
197
197
|
`<<autonomous-loop-dynamic>>` 신호만 보내면 AI가:
|
|
198
198
|
1) 다음 라운드 후보 선정 → 2) 코드 변경 → 3) 회귀 테스트 갱신 → 4) 전체 e2e 스위트 통과 → 5) npm publish + git tag → 6) main push → 7) session close → 8) 다음 라운드 예약.
|
|
199
199
|
|
|
200
|
-
현재 누적: **v1.9.x → 1.36.
|
|
200
|
+
현재 누적: **v1.9.x → 1.36.68 릴리스 태그 이력** (수백 라운드) · _reports/는 비공개 보존.
|
|
201
201
|
|
|
202
202
|
### 성능 가이드
|
|
203
203
|
|
|
@@ -235,5 +235,5 @@ leerness release pack --close --auto-main-push
|
|
|
235
235
|
- `.harness/session-handoff.md`: 다음 세션 인수인계 (자동 작성)
|
|
236
236
|
- `.harness/lessons.md` / `decisions.md` / `rules.md`: 영구 메모리 (5 surface)
|
|
237
237
|
|
|
238
|
-
Last synced by Leerness v1.36.
|
|
238
|
+
Last synced by Leerness v1.36.68: 2026-07-22
|
|
239
239
|
<!-- leerness:project-readme:end -->
|
package/bin/leerness.js
CHANGED
|
@@ -34,7 +34,7 @@ const { CAPABILITY_SURFACE, POWERFUL_COMMANDS, ADAPTERS, REUSE_CATEGORIES, REUSE
|
|
|
34
34
|
const { tokenizeForRank: _tokenizeForRank, expandQuery: _expandQuery, scoreHits: _scoreHits, suggestTerms: _suggestTerms } = require('../lib/search-core'); // 1.36.23: memory search 랭킹 코어(순수·0-deps)
|
|
35
35
|
const { findCorruptedStateJson: _findCorruptedStateJson } = require('../lib/state-integrity'); // 1.36.1 (클린룸 리뷰 FN): .harness/*.json 상태 무결성 (audit/health/check 공유)
|
|
36
36
|
|
|
37
|
-
const VERSION = '1.36.
|
|
37
|
+
const VERSION = '1.36.68';
|
|
38
38
|
|
|
39
39
|
// 1.9.290 (UR-0037, Codex gpt-5.5 #4 수렴): CLI 전용 부작용은 require 시 실행하지 않는다.
|
|
40
40
|
// 이전: warning listener 제거 / NODE_OPTIONS 변경 / chcp IIFE 가 top-level 즉시 실행 → require('harness') 시 호스트 프로세스 오염.
|
package/lib/session-close.js
CHANGED
|
@@ -142,7 +142,19 @@ function sessionClose(root, opts = {}, deps = {}) {
|
|
|
142
142
|
ok(`session-handoff.md and current-state.md updated`);
|
|
143
143
|
// 1.9.12: session close 끝에 roadmap.html 자동 갱신
|
|
144
144
|
_autoRoadmap(root, 'session-close');
|
|
145
|
-
// 1.
|
|
145
|
+
// 1.36.68 (8차 헌트 F14 재구현, 검수: --no-suggest 에서도 노출): 미승인 미리보기(approve 대기)를 마감 보고에 노출 —
|
|
146
|
+
// 1.36.67 이연 원인: 삽입 지점이 jsonMode 전용 후처리 구간이라 텍스트 경로가 도달조차 안 했다.
|
|
147
|
+
// 이제 텍스트 렌더 구간에서 출력하고 JSON 필드는 동일 데이터로 채운다(양 모드 일치).
|
|
148
|
+
try {
|
|
149
|
+
let _pend = [];
|
|
150
|
+
try { _pend = deps.pendingPreviews ? deps.pendingPreviews(root) : require('./clarify').pendingPreviews(root); } catch {}
|
|
151
|
+
jsonResult.pendingPreviews = { count: _pend.length, items: _pend.slice(0, 10).map(p => ({ id: p.id, title: p.title, status: p.status })) };
|
|
152
|
+
if (_pend.length) {
|
|
153
|
+
log(t(` 🎨 미승인 미리보기 ${_pend.length}건 — approve 전 해당 기능 코드 작성 금지`, ` 🎨 ${_pend.length} preview(s) awaiting approval — no code before approve`));
|
|
154
|
+
for (const p of _pend.slice(0, 5)) log(` - ${p.id} ${p.title} [${p.status}]`);
|
|
155
|
+
log(t(' → 승인: leerness preview approve <P-ID> · 수정요구: leerness preview revise <P-ID> --note "..."', ' → approve: leerness preview approve <P-ID> · revise: leerness preview revise <P-ID> --note "..."'));
|
|
156
|
+
}
|
|
157
|
+
} catch {} // 1.9.57: --suggest 옵션 — 마감 시 skill suggest + drift check + lessons 통합 보고
|
|
146
158
|
// 1.9.59: default 활성 — --no-suggest로 명시 비활성 가능
|
|
147
159
|
const suggestEnabled = (has('--suggest') || (!has('--no-suggest') && process.env.LEERNESS_NO_SUGGEST !== '1'));
|
|
148
160
|
if (suggestEnabled) {
|
|
@@ -173,6 +185,7 @@ function sessionClose(root, opts = {}, deps = {}) {
|
|
|
173
185
|
jsonResult.drift = { level: j.level, score: j.score, fired: (j.fired || []).map(f => ({ label: f.label, weight: f.weight })) };
|
|
174
186
|
}
|
|
175
187
|
} catch {}
|
|
188
|
+
|
|
176
189
|
// 3) usage stats top
|
|
177
190
|
try {
|
|
178
191
|
const stats = _readUsageStats(root);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "leerness",
|
|
3
|
-
"version": "1.36.
|
|
3
|
+
"version": "1.36.68",
|
|
4
4
|
"description": "The AI-coding operations layer that makes \"done\" require evidence — persistent memory, evidence-gated completion checks, and clean handoffs for any AI agent (Claude Code, Codex, Cursor). State lives as plain files in your repo. CLI + MCP, 0 runtime dependencies.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"leerness",
|
package/scripts/e2e.js
CHANGED
|
@@ -1444,7 +1444,8 @@ total++;
|
|
|
1444
1444
|
total++;
|
|
1445
1445
|
{
|
|
1446
1446
|
// whats-new --from 큰 점프 → 신규 명령 추출
|
|
1447
|
-
|
|
1447
|
+
// 1.36.68: CHANGELOG 성장으로 응답이 기본 stdout 버퍼(1MB 근처)를 넘어 절단되던 것 — 상한 명시(제품 무변경)
|
|
1448
|
+
const r = cp.spawnSync(process.execPath, [CLI, 'whats-new', '--from', '1.9.33', '--json'], { encoding: 'utf8', timeout: 20000, maxBuffer: 32 * 1024 * 1024 });
|
|
1448
1449
|
let parsed = null;
|
|
1449
1450
|
try { parsed = JSON.parse(r.stdout); } catch {}
|
|
1450
1451
|
const ok = parsed
|
|
@@ -7143,5 +7144,35 @@ total++;
|
|
|
7143
7144
|
if (!ok) failed++;
|
|
7144
7145
|
}
|
|
7145
7146
|
|
|
7147
|
+
// 1.36.68 (8차 헌트 F14 재구현): 마감 보고/JSON 에 미승인 미리보기 노출 — 텍스트·JSON 양 모드 + 승인 후 소거
|
|
7148
|
+
total++;
|
|
7149
|
+
{
|
|
7150
|
+
let ok = false;
|
|
7151
|
+
const _d = [];
|
|
7152
|
+
try {
|
|
7153
|
+
const d = fs.mkdtempSync(path.join(os.tmpdir(), 'leerness-f14-')); _d.push(d);
|
|
7154
|
+
cp.spawnSync(process.execPath, [CLI, 'init', d, '--yes', '--no-env'], { encoding: 'utf8', timeout: 40000 });
|
|
7155
|
+
cp.spawnSync(process.execPath, [CLI, 'preview', 'add', '결제 화면', '--design', '모달', '--path', d], { encoding: 'utf8', timeout: 20000 });
|
|
7156
|
+
const txt = cp.spawnSync(process.execPath, [CLI, 'session', 'close', d], { encoding: 'utf8', timeout: 40000 });
|
|
7157
|
+
const textOk = txt.status === 0 && /미승인 미리보기 1건|1 preview\(s\) awaiting/.test(txt.stdout) && /P-0001/.test(txt.stdout);
|
|
7158
|
+
const js = cp.spawnSync(process.execPath, [CLI, 'session', 'close', d, '--json'], { encoding: 'utf8', timeout: 40000 });
|
|
7159
|
+
let jsonOk = false;
|
|
7160
|
+
try { const j = JSON.parse(js.stdout); jsonOk = j.pendingPreviews && j.pendingPreviews.count === 1 && j.pendingPreviews.items[0].id === 'P-0001'; } catch {}
|
|
7161
|
+
// (검수) --no-suggest 에서도 승인 대기 상태는 노출돼야 — suggest 게이트 밖 배치 회귀 가드
|
|
7162
|
+
const ns = cp.spawnSync(process.execPath, [CLI, 'session', 'close', d, '--no-suggest'], { encoding: 'utf8', timeout: 40000 });
|
|
7163
|
+
const nsJs = cp.spawnSync(process.execPath, [CLI, 'session', 'close', d, '--json', '--no-suggest'], { encoding: 'utf8', timeout: 40000 });
|
|
7164
|
+
let noSuggestOk = /미승인 미리보기|awaiting approval/.test(ns.stdout);
|
|
7165
|
+
try { noSuggestOk = noSuggestOk && JSON.parse(nsJs.stdout).pendingPreviews.count === 1; } catch { noSuggestOk = false; }
|
|
7166
|
+
cp.spawnSync(process.execPath, [CLI, 'preview', 'approve', 'P-0001', '--path', d], { encoding: 'utf8', timeout: 20000 });
|
|
7167
|
+
const after = cp.spawnSync(process.execPath, [CLI, 'session', 'close', d, '--json'], { encoding: 'utf8', timeout: 40000 });
|
|
7168
|
+
let clearedOk = false;
|
|
7169
|
+
try { clearedOk = JSON.parse(after.stdout).pendingPreviews.count === 0; } catch {}
|
|
7170
|
+
ok = textOk && jsonOk && noSuggestOk && clearedOk;
|
|
7171
|
+
if (!ok) console.log(` [f14 디버그] text=${textOk} json=${jsonOk} noSuggest=${noSuggestOk} cleared=${clearedOk}`);
|
|
7172
|
+
} catch (e) {} finally { _d.forEach(x => { try { fs.rmSync(x, { recursive: true, force: true }); } catch {} }); }
|
|
7173
|
+
console.log(ok ? '✓ B(1.36.68) F14: session close 미승인 미리보기 노출 (텍스트+JSON 일치 · --no-suggest 무영향 · 승인 시 소거)' : '✗ F14 미승인 미리보기 노출 실패');
|
|
7174
|
+
if (!ok) failed++;
|
|
7175
|
+
}
|
|
7176
|
+
|
|
7146
7177
|
console.log(`\nE2E result: ${total - failed}/${total} passed · ${((Date.now() - _e2eStart) / 1000).toFixed(0)}s`);
|
|
7147
7178
|
if (failed > 0) process.exit(1);
|