leerness 1.9.142 → 1.9.143

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,27 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.9.143 — 2026-05-20
4
+
5
+ **JSON 4종 featureGraph 통합 완성 + drift check feature 신호** — 1.9.142 session close --json 패턴을 handoff/health에 확장.
6
+
7
+ ### Added — handoff --json featureGraph 통합
8
+ - `result.featureGraph = { total, edges, isolated, summary: "F<n>/E<n>[/iso<n>]" }`
9
+ - 외부 AI가 handoff 한 번에 컨텍스트 + memory surface + featureGraph 동시 회수
10
+
11
+ ### Added — health --json featureGraph 통합
12
+ - `out.featureGraph = { total, edges, isolated, summary }`
13
+ - JSON 4종 (handoff/memory status/session close/health) featureGraph 일관성 완성 (memorySurface 1.9.123 패턴과 동형)
14
+
15
+ ### Added — drift check feature graph 신호 (6번째 신호)
16
+ - 노드 ≥ 3개 + edges == 0 → weight 25
17
+ - 노드 ≥ 3개 + isolated 비율 ≥ 50% → weight 15
18
+ - `drift check --json` `fired` 배열에 노출
19
+ - 사용자 cascade 방지 의지 + 실제 사용 사이 gap 자동 감지
20
+
21
+ ### Validation
22
+ - stress-v88: PASS (handoff/health featureGraph + drift 신호 + 누적 회귀)
23
+ - e2e: 219/219 PASS
24
+
3
25
  ## 1.9.142 — 2026-05-20
4
26
 
5
27
  **Feature Graph 통합 라운드** — 1.9.141 인과관계 시스템을 audit / MCP CRUD / session close 에 통합.
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  > **AI 코딩 에이전트의 거짓 완료·중복·망각·충돌을 막아주는 검수·기억·협업 CLI 하네스.**
4
4
 
5
- [![npm](https://img.shields.io/badge/npm-leerness-blue)](https://www.npmjs.com/package/leerness) [![version](https://img.shields.io/badge/version-1.9.142-green)]() [![tests](https://img.shields.io/badge/e2e-219%2F219-success)]() [![mcp](https://img.shields.io/badge/MCP--tools-46-blue)]() [![json](https://img.shields.io/badge/--json-20_commands-blueviolet)]() [![rounds](https://img.shields.io/badge/autonomous--rounds-72-blueviolet)]() [![main-push](https://img.shields.io/badge/release--main--push-auto-success)]() [![feature-graph](https://img.shields.io/badge/feature--graph--integrated-1.9.142-success)]() [![license](https://img.shields.io/badge/license-MIT-lightgrey)]()
5
+ [![npm](https://img.shields.io/badge/npm-leerness-blue)](https://www.npmjs.com/package/leerness) [![version](https://img.shields.io/badge/version-1.9.143-green)]() [![tests](https://img.shields.io/badge/e2e-219%2F219-success)]() [![mcp](https://img.shields.io/badge/MCP--tools-46-blue)]() [![json](https://img.shields.io/badge/--json-20_commands-blueviolet)]() [![rounds](https://img.shields.io/badge/autonomous--rounds-73-blueviolet)]() [![main-push](https://img.shields.io/badge/release--main--push-auto-success)]() [![feature-graph-json](https://img.shields.io/badge/feature--graph--JSON--4cmds-complete-success)]() [![license](https://img.shields.io/badge/license-MIT-lightgrey)]()
6
6
 
7
7
  ```
8
8
  ╔══════════════════════════════════════════════════════════════╗
@@ -12,7 +12,7 @@
12
12
  ║ ██║ ██╔══╝ ██╔══╝ ██╔══██╗██║╚██╗██║██╔══╝ ╚════██║ ║
13
13
  ║ ███████╗███████╗███████╗██║ ██║██║ ╚████║███████╗███████║ ║
14
14
  ║ ╚══════╝╚══════╝╚══════╝╚═╝ ╚═╝╚═╝ ╚═══╝╚══════╝╚══════╝ ║
15
- ║ v1.9.142 AI Agent Reliability Harness ║
15
+ ║ v1.9.143 AI Agent Reliability Harness ║
16
16
  ║ verify · remember · orchestrate · audit · prevent drift ║
17
17
  ╚══════════════════════════════════════════════════════════════╝
18
18
  ```
package/bin/harness.js CHANGED
@@ -6,7 +6,7 @@ const path = require('path');
6
6
  const cp = require('child_process');
7
7
  const readline = require('readline');
8
8
 
9
- const VERSION = '1.9.142';
9
+ const VERSION = '1.9.143';
10
10
  const MARK = '<!-- leerness:managed -->';
11
11
  const README_START = '<!-- leerness:project-readme:start -->';
12
12
  const README_END = '<!-- leerness:project-readme:end -->';
@@ -2748,6 +2748,22 @@ function handoff(root) {
2748
2748
  archive: archiveCountsH, // 1.9.130
2749
2749
  summary: `T${tasksInProgress}/D${decisionsCount}/R${rulesActive}/P${milestones}/L${lessonsCount}`,
2750
2750
  };
2751
+ // 1.9.143: handoff --json featureGraph 통합 (session close 1.9.142 와 동일 패턴)
2752
+ try {
2753
+ const { nodes: fNodesH } = _readFeatureGraph(root);
2754
+ const edgeCount = fNodesH.reduce((s, n) => s + (n.dependsOn?.length || 0) + (n.affects?.length || 0) + (n.coChangesWith?.length || 0), 0);
2755
+ const linkedSet = new Set();
2756
+ for (const n of fNodesH) {
2757
+ for (const x of [...(n.dependsOn||[]), ...(n.affects||[]), ...(n.coChangesWith||[])]) { linkedSet.add(n.id); linkedSet.add(x); }
2758
+ }
2759
+ const isolated = fNodesH.length ? (fNodesH.length - linkedSet.size) : 0;
2760
+ result.featureGraph = {
2761
+ total: fNodesH.length,
2762
+ edges: edgeCount,
2763
+ isolated: Math.max(0, isolated),
2764
+ summary: `F${fNodesH.length}/E${edgeCount}${isolated > 0 ? `/iso${isolated}` : ''}`
2765
+ };
2766
+ } catch {}
2751
2767
  } catch {}
2752
2768
  log(JSON.stringify(result, null, 2));
2753
2769
  return;
@@ -4582,7 +4598,7 @@ function _banner(opts = {}) {
4582
4598
  for (const ln of lines) log(ln);
4583
4599
  }
4584
4600
  if (opts.quickStart) {
4585
- log(C.bold(C.cyan(' ✨ 빠른 시작 (1.9.142+ Feature Graph 통합: MCP CRUD + audit 검증 + session close 72 라운드 자율 누적)')));
4601
+ log(C.bold(C.cyan(' ✨ 빠른 시작 (1.9.143+ JSON 4종 featureGraph 통합 완성 + drift 신호73 라운드 자율 누적)')));
4586
4602
  log(' ' + C.green('npx leerness@latest init .') + C.dim(' # 신규 프로젝트 + 외부 AI CLI 설정'));
4587
4603
  log(' ' + C.green('npx leerness handoff .') + C.dim(' # 컨텍스트 + lessons + 매칭 skill + history hit + brainstorm hits + 헤드라인'));
4588
4604
  log(' ' + C.green('npx leerness handoff . --quiet') + C.dim(' # 자동화/CI 모드 (1.9.99) — 자동 회수 라인 비활성'));
@@ -8200,6 +8216,24 @@ function driftCheckCmd(root, opts = {}) {
8200
8216
  }
8201
8217
  }
8202
8218
  } catch {}
8219
+ // 1.9.143: Feature Graph 미사용 신호 — 노드는 있는데 edges 비율 낮으면 인과관계 정리 미진
8220
+ try {
8221
+ const { nodes: fGraphNodes } = _readFeatureGraph(root);
8222
+ if (fGraphNodes.length >= 3) {
8223
+ const edgeCount = fGraphNodes.reduce((s, n) => s + (n.dependsOn?.length || 0) + (n.affects?.length || 0) + (n.coChangesWith?.length || 0), 0);
8224
+ const linkedSet = new Set();
8225
+ for (const n of fGraphNodes) {
8226
+ for (const x of [...(n.dependsOn||[]), ...(n.affects||[]), ...(n.coChangesWith||[])]) { linkedSet.add(n.id); linkedSet.add(x); }
8227
+ }
8228
+ const isolatedCount = Math.max(0, fGraphNodes.length - linkedSet.size);
8229
+ const isolatedRatio = isolatedCount / fGraphNodes.length;
8230
+ if (edgeCount === 0 || isolatedRatio >= 0.5) {
8231
+ const fgScore = edgeCount === 0 ? 25 : 15;
8232
+ totalScore += fgScore;
8233
+ fired.push({ file: '.harness/feature-graph.md', ageDays: null, threshold: 0, weight: fgScore, label: `Feature Graph 미정리 (1.9.143): ${fGraphNodes.length} 노드, edges=${edgeCount}, isolated=${isolatedCount}` });
8234
+ }
8235
+ }
8236
+ } catch {}
8203
8237
  // 신규 _apps/* 에서 task 0건도 신호로
8204
8238
  const appsDir = path.join(root, '_apps');
8205
8239
  let appsZeroTask = [];
@@ -9600,6 +9634,22 @@ function healthCmd(root) {
9600
9634
  summary: `T${tasksInProgress}/D${decisionsCount}/R${rulesActive}/P${milestones}/L${lessonsCount}`,
9601
9635
  };
9602
9636
  } catch { out.memorySurface = { error: 'memorySurface 점검 실패' }; }
9637
+ // 1.9.143: health --json featureGraph 통합 (handoff/session close 와 동일 패턴 — JSON 4종 완성)
9638
+ try {
9639
+ const { nodes: fNodesHe } = _readFeatureGraph(root);
9640
+ const edgeCount = fNodesHe.reduce((s, n) => s + (n.dependsOn?.length || 0) + (n.affects?.length || 0) + (n.coChangesWith?.length || 0), 0);
9641
+ const linkedSet = new Set();
9642
+ for (const n of fNodesHe) {
9643
+ for (const x of [...(n.dependsOn||[]), ...(n.affects||[]), ...(n.coChangesWith||[])]) { linkedSet.add(n.id); linkedSet.add(x); }
9644
+ }
9645
+ const isolated = fNodesHe.length ? (fNodesHe.length - linkedSet.size) : 0;
9646
+ out.featureGraph = {
9647
+ total: fNodesHe.length,
9648
+ edges: edgeCount,
9649
+ isolated: Math.max(0, isolated),
9650
+ summary: `F${fNodesHe.length}/E${edgeCount}${isolated > 0 ? `/iso${isolated}` : ''}`
9651
+ };
9652
+ } catch { out.featureGraph = { error: 'featureGraph 점검 실패' }; }
9603
9653
  // 6) issues 요약 (사용자 글로벌 룰 가시화)
9604
9654
  const issues = [];
9605
9655
  if (out.checks.drift?.level && !/healthy/.test(out.checks.drift.level)) issues.push(`drift ${out.checks.drift.level}`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "leerness",
3
- "version": "1.9.142",
3
+ "version": "1.9.143",
4
4
  "description": "Leerness: 비파괴 마이그레이션, 자동 버전 감지·업데이트, 계획/진행/핸드오프 자동화, 게으름·시크릿·인코딩 자동 가드, Claude Code 슬래시 통합을 갖춘 한국어 우선 AI 개발 하네스.",
5
5
  "keywords": [
6
6
  "leerness",