leerness 1.36.46 → 1.36.47
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 +13 -4
- package/lib/pure-utils.js +11 -2
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.36.47 — 2026-07-16 — anchors 초안 품질 + 재초안 — 실프로젝트 6곳 실적용에서 발견·즉시 교정
|
|
4
|
+
|
|
5
|
+
사용자 승인 하에 실프로젝트 6곳(hive-analytics/auto-macro/cafe-macro/blog-macro/view-work/AEGIRINE)을 1.36.46 으로 **무유실 마이그레이션**(5표면 카운트 전량 보존, auto-macro 는 1.9.441→46 32버전 점프에 CLAUDE 커스텀 포함 무손실 — 보존 3부작의 실전 입증)하고 anchors 초안을 일괄 적용한 결과, 실데이터에서 초안 품질 결함 2종 발견:
|
|
6
|
+
|
|
7
|
+
- **어색문**: goal 문형의 조사 병기("…를(을) 동작하는…") + 160자 **구 중간 절단**("주문 목록 를(을)") → 단어/구두점 경계 절단(`…` 표시) + 조사 없는 문형("제품을 동작 상태로 유지·발전시킨다: <설명>")으로 교정.
|
|
8
|
+
- **재초안 불가**: 초안 적용 후엔 "작성됨" 판정이라 품질 개선을 전파할 수 없었음 → **draft 마커가 남아있는 섹션은 재초안 대상**(확정본 = 마커 제거본은 불가침 유지). 실측: 6곳 재적용 — draft 섹션만 갱신(2/2/1/2/1), 사용자 작성 2섹션 + AEGIRINE 완정본 0 접촉, 어색문 잔존 0.
|
|
9
|
+
- (부수: `_mdSectionBody` bin 임포트 누락을 라이브 실행이 즉시 노출 — selftest 는 anchorsCmd 미실행이라 못 잡음. 임포트 추가.)
|
|
10
|
+
- **검증**: selftest 316/316(문형·경계절단·재초안 배선 가드 보강), 실프로젝트 6곳 재적용 실측, exit 전파형 게이트 e2e, 클린룸.
|
|
11
|
+
|
|
3
12
|
## 1.36.46 — 2026-07-16 — JSON 계약 완결 — persona/review/guide (codex 5차 #10 잔여 소진)
|
|
4
13
|
|
|
5
14
|
`--json` 을 광고하면서 마크다운/혼합 출력을 내던 마지막 3종 — MCP·자동화 소비자가 파싱 가능한 **단일 JSON 문서**로:
|
package/README.md
CHANGED
|
@@ -121,7 +121,7 @@ MIT
|
|
|
121
121
|
<!-- leerness:project-readme:start -->
|
|
122
122
|
## Leerness Project Harness
|
|
123
123
|
|
|
124
|
-
이 프로젝트는 Leerness v1.36.
|
|
124
|
+
이 프로젝트는 Leerness v1.36.47 하네스를 사용합니다. AI 에이전트는 작업 전 `leerness handoff`로 컨텍스트를 적재하고, 작업 후 `leerness check`/`leerness audit`/`leerness session close`를 수행해야 합니다.
|
|
125
125
|
|
|
126
126
|
### 정체성 — AI 에이전트 운영 레이어 (UR-0030)
|
|
127
127
|
|
|
@@ -175,7 +175,7 @@ leerness memory restore decision <date|title>
|
|
|
175
175
|
|
|
176
176
|
### MCP server (외부 AI 통합)
|
|
177
177
|
|
|
178
|
-
Leerness v1.36.
|
|
178
|
+
Leerness v1.36.47는 stdio JSON-RPC MCP server를 내장합니다 — Claude Code · Cursor · Codex CLI 등 외부 AI에 **86개 도구**를 노출:
|
|
179
179
|
|
|
180
180
|
```jsonc
|
|
181
181
|
// 카테고리별
|
|
@@ -196,7 +196,7 @@ Leerness v1.36.46는 stdio JSON-RPC MCP server를 내장합니다 — Claude Cod
|
|
|
196
196
|
`<<autonomous-loop-dynamic>>` 신호만 보내면 AI가:
|
|
197
197
|
1) 다음 라운드 후보 선정 → 2) 코드 변경 → 3) 회귀 테스트 갱신 → 4) 전체 e2e 스위트 통과 → 5) npm publish + git tag → 6) main push → 7) session close → 8) 다음 라운드 예약.
|
|
198
198
|
|
|
199
|
-
현재 누적: **v1.9.x → 1.36.
|
|
199
|
+
현재 누적: **v1.9.x → 1.36.47 릴리스 태그 이력** (수백 라운드) · _reports/는 비공개 보존.
|
|
200
200
|
|
|
201
201
|
### 성능 가이드
|
|
202
202
|
|
|
@@ -234,6 +234,6 @@ leerness release pack --close --auto-main-push
|
|
|
234
234
|
- `.harness/session-handoff.md`: 다음 세션 인수인계 (자동 작성)
|
|
235
235
|
- `.harness/lessons.md` / `decisions.md` / `rules.md`: 영구 메모리 (5 surface)
|
|
236
236
|
|
|
237
|
-
Last synced by Leerness v1.36.
|
|
237
|
+
Last synced by Leerness v1.36.47: 2026-07-21
|
|
238
238
|
<!-- leerness:project-readme:end -->
|
|
239
239
|
|
package/bin/leerness.js
CHANGED
|
@@ -26,7 +26,7 @@ const { _isSecretKey, _isPlaceholderSecret, _looksSecretLike, _mergeLines, _merg
|
|
|
26
26
|
_migrationGuideText, _parseContractSpec, _gitignoreMatch,
|
|
27
27
|
_featureGraphTemplate, _parseFeatureGraph, _nextFeatureId, _featureBlock, _featureImpactBfs,
|
|
28
28
|
_parseChangelogBetween, _cellSafe, _cellUnescape, _lineSafe, _parseLimit, _parseAddTitle, _parseImplExports, _taskPositionalPath, _completionClaimAllowed, _minorKey, _shouldPublishNpm,
|
|
29
|
-
_matchTool, _parsePackageJsonDeps, _parseRequirementsTxt, _buildGlossary, _renderGlossaryMd, _briefUnfilled, _planGoalUnfilled, _draftAnchors, _replaceMdSection } = require('../lib/pure-utils'); // 1.9.318~1.11.4 (UR-0025/.../0007 glossary): 순수 유틸 모듈 분리 · 1.36.36 anchors
|
|
29
|
+
_matchTool, _parsePackageJsonDeps, _parseRequirementsTxt, _buildGlossary, _renderGlossaryMd, _briefUnfilled, _planGoalUnfilled, _draftAnchors, _replaceMdSection, _mdSectionBody } = require('../lib/pure-utils'); // 1.9.318~1.11.4 (UR-0025/.../0007 glossary): 순수 유틸 모듈 분리 · 1.36.36 anchors
|
|
30
30
|
// 1.9.304 (UR-0025): 순수 분석/검증 함수 모듈 분리.
|
|
31
31
|
const { _evidenceQuality, _parseEvidenceStats, _shellGuardAnalyze, _claimFileInGit, _epistemicHonestyCheck } = require('../lib/analyzers');
|
|
32
32
|
// 1.9.295 (UR-0025 4단계): 정적 데이터 카탈로그 모듈 분리 (비파괴, require-based).
|
|
@@ -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.47';
|
|
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') 시 호스트 프로세스 오염.
|
|
@@ -3202,6 +3202,13 @@ function _selfTestCases() {
|
|
|
3202
3202
|
if (typeof p._draftAnchors !== 'function' || typeof p._replaceMdSection !== 'function') return false;
|
|
3203
3203
|
const d = p._draftAnchors({ pkgDescription: '결제 정산 서비스', readmeText: '# T\n\n웹훅 백엔드.\n', milestones: [{ id: 'M-0001', title: '베타', status: 'planned' }], tasks: [] });
|
|
3204
3204
|
const draftOk = d.hasSignal && d.purpose.some(l => l.includes('결제 정산 서비스')) && d.goal.some(l => l.includes('M-0001')) && d.purpose[0].includes('draft:');
|
|
3205
|
+
// 1.36.47: 어색 조사 병기 소거 + 장문은 단어 경계 절단(…) — 실적용에서 발견된 품질 결함 회귀 방지
|
|
3206
|
+
const dLong = p._draftAnchors({ pkgDescription: '가나다 라마바사 아자차카 타파하 '.repeat(20) });
|
|
3207
|
+
const phraseOk = !dLong.goal.join('').includes('를(을)') && dLong.goal.some(l => l.includes('…')) && !/[가-힣]{2}…[가-힣]/.test(dLong.goal.join(''));
|
|
3208
|
+
// 재초안: draft 마커 잔존 섹션은 gap 취급 (배선 소스가드)
|
|
3209
|
+
const s47 = read(__filename);
|
|
3210
|
+
const redraftOk = s47.includes("_mdSectionBody(briefTxt, 'Purpose') || '').includes(_draftM)");
|
|
3211
|
+
if (!(phraseOk && redraftOk)) return false;
|
|
3205
3212
|
// 무신호 시 발명 금지
|
|
3206
3213
|
const empty = p._draftAnchors({});
|
|
3207
3214
|
const noInvent = !empty.hasSignal && empty.purpose.length === 0 && empty.goal.length === 0;
|
|
@@ -5196,8 +5203,10 @@ function anchorsCmd(root, sub) {
|
|
|
5196
5203
|
const briefTxt = exists(bf) ? read(bf) : '';
|
|
5197
5204
|
const planTxt = exists(pf) ? read(pf) : '';
|
|
5198
5205
|
const naM = '<!-- leerness:na';
|
|
5199
|
-
|
|
5200
|
-
const
|
|
5206
|
+
// 1.36.47: draft 마커가 남아있는 섹션(미확정 초안)은 재초안 대상 — 초안 품질 개선을 기존 적용본에도 전파 가능.
|
|
5207
|
+
const _draftM = '<!-- draft: leerness anchors';
|
|
5208
|
+
const briefGap = !!briefTxt && !briefTxt.includes(naM) && (_briefUnfilled(briefTxt) || (_mdSectionBody(briefTxt, 'Purpose') || '').includes(_draftM));
|
|
5209
|
+
const planGap = !!planTxt && !planTxt.includes(naM) && (_planGoalUnfilled(planTxt) || (_mdSectionBody(planTxt, 'Goal') || '').includes(_draftM));
|
|
5201
5210
|
if (!sub || sub === 'status') {
|
|
5202
5211
|
if (json) { log(JSON.stringify({ briefUnfilled: briefGap, planGoalUnfilled: planGap }, null, 2)); return; }
|
|
5203
5212
|
log(`# leerness anchors — 정체성앵커 상태`);
|
package/lib/pure-utils.js
CHANGED
|
@@ -1159,11 +1159,20 @@ function _draftAnchors(sig = {}) {
|
|
|
1159
1159
|
if (!t || t.startsWith('#') || t.startsWith('![') || t.startsWith('[!') || t.startsWith('<')) continue;
|
|
1160
1160
|
readmeLead = t; break;
|
|
1161
1161
|
}
|
|
1162
|
+
// 1.36.47 (실적용 품질 결함): slice 가 구 중간을 절단해 "…주문 목록 를(을)…" 같은 어색문이 실프로젝트에 박혔다 —
|
|
1163
|
+
// 단어/구두점 경계 절단 + 조사 병기 없는 문형으로.
|
|
1164
|
+
const _cutAt = (s, n) => {
|
|
1165
|
+
s = String(s || '').trim();
|
|
1166
|
+
if (s.length <= n) return s;
|
|
1167
|
+
const head = s.slice(0, n);
|
|
1168
|
+
const brk = Math.max(head.lastIndexOf(' '), head.lastIndexOf(','), head.lastIndexOf('·'), head.lastIndexOf('。'), head.lastIndexOf('.'));
|
|
1169
|
+
return (brk > n * 0.5 ? head.slice(0, brk) : head).replace(/[\s,·]+$/, '') + '…';
|
|
1170
|
+
};
|
|
1162
1171
|
if (desc) purpose.push(`- ${desc}`);
|
|
1163
|
-
if (readmeLead && readmeLead !== desc) purpose.push(`- ${readmeLead
|
|
1172
|
+
if (readmeLead && readmeLead !== desc) purpose.push(`- ${_cutAt(readmeLead, 200)}`);
|
|
1164
1173
|
const ms = (sig.milestones || []).filter(m => m && m.title).slice(0, 3);
|
|
1165
1174
|
const activeTasks = (sig.tasks || []).filter(t => t && /in-progress|planned|requested/.test(String(t.status || ''))).slice(0, 3);
|
|
1166
|
-
if (desc || readmeLead) goal.push(`- ${(desc || readmeLead
|
|
1175
|
+
if (desc || readmeLead) goal.push(`- 제품을 동작 상태로 유지·발전시킨다: ${_cutAt(desc || readmeLead, 140)}`);
|
|
1167
1176
|
for (const m of ms) goal.push(`- [${m.id || 'M'}] ${String(m.title).slice(0, 120)}${m.status ? ` (${m.status})` : ''}`);
|
|
1168
1177
|
if (!goal.length && activeTasks.length) for (const t of activeTasks) goal.push(`- ${t.id}: ${String(t.request || '').slice(0, 100)}`);
|
|
1169
1178
|
const marker = '<!-- draft: leerness anchors — 실신호 기반 초안. AI/사용자가 검토·수정 후 이 주석을 지우면 확정 -->';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "leerness",
|
|
3
|
-
"version": "1.36.
|
|
3
|
+
"version": "1.36.47",
|
|
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",
|