leerness 1.36.46 → 1.36.48

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,18 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.36.48 — 2026-07-16 — ACP 입장 명문화 (docs/interoperability.md, 사용자 질의)
4
+
5
+ 사용자 질의("ACP 가 고려돼 있는가?")에 대한 검토 결과 언급 0 — "미고려" 를 "고려 후 결정" 으로 전환. **Agent Client Protocol**(Zed 계열): 에디터↔에이전트 토폴로지라 운영 레이어인 leerness 에 직접 구현 자리 없음 — ACP 에이전트는 MCP(.mcp.json) 경유로 이미 간접 호환, enforce 는 프로토콜 무관 커버. **Agent Communication Protocol**(BeeAI, REST): 오프라인-퍼스트/0-deps 원칙 충돌 — 동일 문제는 .leerness/ substrate 가 해결. 상호운용성 문서 신설(지원 표면 표 + 신규 프로토콜 평가 기준 3항 + 재검토 트리거), README Links 연결, decision 기록.
6
+
7
+ ## 1.36.47 — 2026-07-16 — anchors 초안 품질 + 재초안 — 실프로젝트 6곳 실적용에서 발견·즉시 교정
8
+
9
+ 사용자 승인 하에 실프로젝트 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종 발견:
10
+
11
+ - **어색문**: goal 문형의 조사 병기("…를(을) 동작하는…") + 160자 **구 중간 절단**("주문 목록 를(을)") → 단어/구두점 경계 절단(`…` 표시) + 조사 없는 문형("제품을 동작 상태로 유지·발전시킨다: <설명>")으로 교정.
12
+ - **재초안 불가**: 초안 적용 후엔 "작성됨" 판정이라 품질 개선을 전파할 수 없었음 → **draft 마커가 남아있는 섹션은 재초안 대상**(확정본 = 마커 제거본은 불가침 유지). 실측: 6곳 재적용 — draft 섹션만 갱신(2/2/1/2/1), 사용자 작성 2섹션 + AEGIRINE 완정본 0 접촉, 어색문 잔존 0.
13
+ - (부수: `_mdSectionBody` bin 임포트 누락을 라이브 실행이 즉시 노출 — selftest 는 anchorsCmd 미실행이라 못 잡음. 임포트 추가.)
14
+ - **검증**: selftest 316/316(문형·경계절단·재초안 배선 가드 보강), 실프로젝트 6곳 재적용 실측, exit 전파형 게이트 e2e, 클린룸.
15
+
3
16
  ## 1.36.46 — 2026-07-16 — JSON 계약 완결 — persona/review/guide (codex 5차 #10 잔여 소진)
4
17
 
5
18
  `--json` 을 광고하면서 마크다운/혼합 출력을 내던 마지막 3종 — MCP·자동화 소비자가 파싱 가능한 **단일 JSON 문서**로:
package/README.md CHANGED
@@ -112,6 +112,7 @@ Full command reference, workflows, and architecture: **[README.ko.md](./README.k
112
112
  - Site & release videos: https://leerness.pages.dev
113
113
  - Changelog: [CHANGELOG.md](./CHANGELOG.md)
114
114
  - How this gets tested — methodology, results, and limitations: [docs/clean-room-evaluations.md](./docs/clean-room-evaluations.md)
115
+ - Interoperability (MCP · ACP stance · state substrate): [docs/interoperability.md](./docs/interoperability.md)
115
116
  - Contributing & test tiers (`test:fast` / `test:core` / `npm test`): [CONTRIBUTING.md](./CONTRIBUTING.md)
116
117
 
117
118
  ## License
@@ -121,7 +122,7 @@ MIT
121
122
  <!-- leerness:project-readme:start -->
122
123
  ## Leerness Project Harness
123
124
 
124
- 이 프로젝트는 Leerness v1.36.46 하네스를 사용합니다. AI 에이전트는 작업 전 `leerness handoff`로 컨텍스트를 적재하고, 작업 후 `leerness check`/`leerness audit`/`leerness session close`를 수행해야 합니다.
125
+ 이 프로젝트는 Leerness v1.36.48 하네스를 사용합니다. AI 에이전트는 작업 전 `leerness handoff`로 컨텍스트를 적재하고, 작업 후 `leerness check`/`leerness audit`/`leerness session close`를 수행해야 합니다.
125
126
 
126
127
  ### 정체성 — AI 에이전트 운영 레이어 (UR-0030)
127
128
 
@@ -175,7 +176,7 @@ leerness memory restore decision <date|title>
175
176
 
176
177
  ### MCP server (외부 AI 통합)
177
178
 
178
- Leerness v1.36.46는 stdio JSON-RPC MCP server를 내장합니다 — Claude Code · Cursor · Codex CLI 등 외부 AI에 **86개 도구**를 노출:
179
+ Leerness v1.36.48는 stdio JSON-RPC MCP server를 내장합니다 — Claude Code · Cursor · Codex CLI 등 외부 AI에 **86개 도구**를 노출:
179
180
 
180
181
  ```jsonc
181
182
  // 카테고리별
@@ -196,7 +197,7 @@ Leerness v1.36.46는 stdio JSON-RPC MCP server를 내장합니다 — Claude Cod
196
197
  `<<autonomous-loop-dynamic>>` 신호만 보내면 AI가:
197
198
  1) 다음 라운드 후보 선정 → 2) 코드 변경 → 3) 회귀 테스트 갱신 → 4) 전체 e2e 스위트 통과 → 5) npm publish + git tag → 6) main push → 7) session close → 8) 다음 라운드 예약.
198
199
 
199
- 현재 누적: **v1.9.x → 1.36.46 릴리스 태그 이력** (수백 라운드) · _reports/는 비공개 보존.
200
+ 현재 누적: **v1.9.x → 1.36.48 릴리스 태그 이력** (수백 라운드) · _reports/는 비공개 보존.
200
201
 
201
202
  ### 성능 가이드
202
203
 
@@ -234,6 +235,6 @@ leerness release pack --close --auto-main-push
234
235
  - `.harness/session-handoff.md`: 다음 세션 인수인계 (자동 작성)
235
236
  - `.harness/lessons.md` / `decisions.md` / `rules.md`: 영구 메모리 (5 surface)
236
237
 
237
- Last synced by Leerness v1.36.46: 2026-07-16
238
+ Last synced by Leerness v1.36.48: 2026-07-21
238
239
  <!-- leerness:project-readme:end -->
239
240
 
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.46';
37
+ const VERSION = '1.36.48';
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
- const briefGap = !!briefTxt && !briefTxt.includes(naM) && _briefUnfilled(briefTxt);
5200
- const planGap = !!planTxt && !planTxt.includes(naM) && _planGoalUnfilled(planTxt);
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 — 정체성앵커 상태`);
@@ -0,0 +1,33 @@
1
+ # 상호운용성 (Interoperability) — leerness 의 프로토콜 입장
2
+
3
+ leerness 는 **에이전트도 에디터도 아닌, 에이전트 위의 운영 레이어**다. 이 위치가 각 프로토콜에 대한 입장을 결정한다.
4
+
5
+ ## 지원 표면 (구현됨)
6
+
7
+ | 표면 | 형태 | 용도 |
8
+ |---|---|---|
9
+ | **CLI** | 명령줄 | 모든 에이전트/사람의 기본 진입점 |
10
+ | **MCP** (`leerness mcp serve`) | stdio JSON-RPC, 86 도구 | 외부 AI 가 자연어→도구 호출로 직접 사용. `adapter <tool>` 이 `.mcp.json` 자동 병합 |
11
+ | **`.leerness/` state substrate** | 파일(JSON) | 에이전트 간 인수인계 표준 — Claude Code 가 한 작업을 Codex/Goose 가 이어받음. 오프라인·0-deps |
12
+ | **지침 계층** | AGENTS.md / CLAUDE.md / 전역 조건부(`adapter codex --global`) | 문서를 읽는 에이전트 대상 협조 계층 |
13
+ | **강제 계층** | `enforce`(pre-commit) + `ci init`(gate) | **프로토콜 무관** — 어떤 방식으로 붙은 에이전트든 커밋/PR 관문에서 검증 |
14
+
15
+ ## ACP — Agent Client Protocol (Zed 계열, 에디터↔에이전트)
16
+
17
+ **입장: 직접 구현하지 않는다 (고려 후 결정, 2026-07).**
18
+
19
+ - ACP 의 토폴로지는 에디터(클라이언트) ↔ 코딩 에이전트(서버)다. leerness 는 그 어느 쪽도 아니므로 ACP 서버/클라이언트를 구현할 구조적 자리가 없다.
20
+ - **간접 호환은 이미 성립**: ACP 로 에디터에 붙는 에이전트(Claude Code ACP 어댑터, Gemini CLI 등)는 도구 계층으로 MCP 를 사용한다 → 프로젝트의 `.mcp.json`(leerness adapter 가 병합)을 통해 leerness 86 도구에 그대로 접근한다.
21
+ - **강제는 이미 커버**: pre-commit enforce 는 접속 프로토콜과 무관하게 작동한다(커밋이 보편 관문).
22
+ - 재검토 트리거: ACP 가 에이전트-측 도구 계층으로 MCP 외 자체 도구 규격을 강제하게 되는 경우.
23
+
24
+ ## ACP — Agent Communication Protocol (BeeAI/Linux Foundation, 에이전트↔에이전트 REST)
25
+
26
+ **입장: 채택하지 않는다.**
27
+
28
+ - 서버 상주형 REST 는 leerness 의 오프라인-퍼스트·0-deps·plain-files 원칙과 충돌한다.
29
+ - 같은 문제(에이전트 간 인수인계)는 `.leerness/` substrate 가 파일 기반으로 해결한다 — 리포에 남고, 네트워크가 없어도 동작하며, 어떤 에이전트든 읽을 수 있다.
30
+
31
+ ## 요약
32
+
33
+ 새 프로토콜 평가 기준: **(1) leerness 의 역할(운영 레이어)에 자리가 있는가, (2) MCP/파일 substrate 로 이미 닿는가, (3) 오프라인·0-deps 원칙과 정합한가.** ACP 두 종 모두 (2)에서 이미 충족되거나 (3)에서 탈락한다 — 상태 변화 시 이 문서를 갱신한다.
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.slice(0, 200)}`);
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).slice(0, 160)} 를(을) 동작하는 제품으로 유지·발전시킨다`);
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.46",
3
+ "version": "1.36.48",
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",