leerness 1.9.231 β†’ 1.9.232

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,37 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.9.232 β€” 2026-05-23
4
+
5
+ **πŸ› pulse memorySurface BUG fix + handoff --pulse μ˜΅μ…˜ + session close μžλ™ pulse.**
6
+
7
+ ### 1. pulse memorySurface BUG fix (1.9.231 β†’ 1.9.232)
8
+ - 1.9.231 pulse 의 T/D/R/P/L μΉ΄μš΄νŠΈκ°€ 잘λͺ»λœ μ •κ·œμ‹μœΌλ‘œ 늘 0 좜λ ₯
9
+ - 1.9.232: `memoryStatusCmd` 와 λ™μΌν•œ νŒ¨ν„΄ μ‚¬μš© (`readProgressRows`, `_extractDecisionBlocks`, `readRules`, `### M-` regex, `### YYYY-MM-DD` regex)
10
+ - 검증: leerness-pkg β†’ κΈ°μ‘΄ `T0/D0/R0/P0/L0` β†’ 정상 `T0/D0/R1/P1/L0` (active rule + milestone 반영)
11
+
12
+ ### 2. `leerness handoff --pulse` μ˜΅μ…˜ μ‹ μ„€
13
+ - handoff λŒ€μ‹  pulse 1 line ν˜•μ‹ 좜λ ₯
14
+ - AI κ°€ λΉ λ₯Έ μƒνƒœ 확인 μ‹œ μ‚¬μš© (`handoff` 전체 호좜 λŒ€μ‹ )
15
+ - λ‚΄λΆ€: `pulseCmd` 직접 호좜
16
+
17
+ ### 3. session close μžλ™ pulse ν•œ 쀄 λ…ΈμΆœ
18
+ - 마감 μ‹œ 1.9.217 톡합 보고 끝에 pulse ν•œ 쀄 μžλ™ μΆ”κ°€
19
+ - λ‹€μŒ λΌμš΄λ“œ μ§„μž… μ‹œ μ¦‰μ‹œ μƒνƒœ 인지: `πŸ“ v1.9.232 Β· πŸ”„ R188 Β· 🧠 T0/D0/R1/P1/L0 Β· 🎯 R200 (1d)`
20
+ - AI κ°€ ν•œ μ€„λ‘œ μ»¨ν…μŠ€νŠΈ 확보
21
+
22
+ ### 4. λˆ„μ  νšŒκ·€ (1.9.207~231) β€” λͺ¨λ‘ μœ μ§€
23
+
24
+ ### 5. stress-v177 β€” 13/13 PASS
25
+ - 1.9.232 (4): VERSION + pulse BUG fix + handoff --pulse + session close μžλ™ pulse
26
+ - μ„±λŠ₯ (2): cold_start avg 389ms / pulse 1009ms
27
+ - λˆ„μ  νšŒκ·€ (7): 1.9.207~231
28
+
29
+ ### 6. μžλ™ release (94 λΌμš΄λ“œ main-push streak Β· 55 λΌμš΄λ“œ npm publish streak)
30
+
31
+ πŸ› **1 λΌμš΄λ“œ BUG fix + 2 UX κ°œμ„ ** β€” pulse μ‹œμŠ€ν…œ μ•ˆμ •μ„± κ°•ν™”
32
+
33
+ ---
34
+
3
35
  ## 1.9.231 β€” 2026-05-23
4
36
 
5
37
  **πŸ“ leerness pulse μƒˆ λͺ…λ Ή (ν•œ 쀄 μ’…ν•© μš”μ•½) + MCP 64번째 도ꡬ.**
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.231-green)]() [![tests](https://img.shields.io/badge/e2e-217%2F217-success)]() [![stress](https://img.shields.io/badge/stress--v176-16%2F16-success)]() [![mcp](https://img.shields.io/badge/MCP--tools-64-brightgreen)]() [![rounds](https://img.shields.io/badge/autonomous--rounds-187-blueviolet)]() [![main-push](https://img.shields.io/badge/release--main--push-93_rounds-success)]() [![goal-matrix](https://img.shields.io/badge/λͺ©μ _맀트릭슀-100%2F100_(5μΆ•)-brightgreen)]() [![pulse](https://img.shields.io/badge/πŸ“_pulse-ν•œ_쀄_μ’…ν•©_μš”μ•½-blueviolet)]() [![perf](https://img.shields.io/badge/cold_start-394ms-success)]() [![install](https://img.shields.io/badge/npm_i_leerness-μ¦‰μ‹œ_μ‚¬μš©_κ°€λŠ₯-success)]() [![sandbox](https://img.shields.io/badge/runCommandSafe-cwd_jail%2Benv_scrub-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.232-green)]() [![tests](https://img.shields.io/badge/e2e-217%2F217-success)]() [![stress](https://img.shields.io/badge/stress--v177-13%2F13-success)]() [![mcp](https://img.shields.io/badge/MCP--tools-64-brightgreen)]() [![rounds](https://img.shields.io/badge/autonomous--rounds-188-blueviolet)]() [![main-push](https://img.shields.io/badge/release--main--push-94_rounds-success)]() [![goal-matrix](https://img.shields.io/badge/λͺ©μ _맀트릭슀-100%2F100_(5μΆ•)-brightgreen)]() [![bugfix](https://img.shields.io/badge/πŸ›_pulse-BUG_fix-blueviolet)]() [![perf](https://img.shields.io/badge/cold_start-389ms-success)]() [![install](https://img.shields.io/badge/npm_i_leerness-μ¦‰μ‹œ_μ‚¬μš©_κ°€λŠ₯-success)]() [![sandbox](https://img.shields.io/badge/runCommandSafe-cwd_jail%2Benv_scrub-success)]() [![license](https://img.shields.io/badge/license-MIT-lightgrey)]()
6
6
 
7
7
  ```
8
8
  ╔══════════════════════════════════════════════════════════════╗
@@ -12,9 +12,9 @@
12
12
  β•‘ β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ•”β•β•β• β–ˆβ–ˆβ•”β•β•β• β–ˆβ–ˆβ•”β•β•β–ˆβ–ˆβ•—β–ˆβ–ˆβ•‘β•šβ–ˆβ–ˆβ•—β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•”β•β•β• β•šβ•β•β•β•β–ˆβ–ˆβ•‘ β•‘
13
13
  β•‘ β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•‘ β•šβ–ˆβ–ˆβ–ˆβ–ˆβ•‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•‘ β•‘
14
14
  β•‘ β•šβ•β•β•β•β•β•β•β•šβ•β•β•β•β•β•β•β•šβ•β•β•β•β•β•β•β•šβ•β• β•šβ•β•β•šβ•β• β•šβ•β•β•β•β•šβ•β•β•β•β•β•β•β•šβ•β•β•β•β•β•β• β•‘
15
- β•‘ v1.9.231 AI Agent Reliability Harness + Sandbox β•‘
15
+ β•‘ v1.9.232 AI Agent Reliability Harness + Sandbox β•‘
16
16
  β•‘ verify Β· remember Β· orchestrate Β· audit Β· sandbox Β· drift β•‘
17
- β•‘ πŸ“ leerness pulse β€” ν•œ 쀄 μ’…ν•© μš”μ•½ + MCP 64 도ꡬ β•‘
17
+ β•‘ πŸ› pulse BUG fix Β· handoff --pulse Β· session close μžλ™ β•‘
18
18
  β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•
19
19
  ```
20
20
 
package/bin/harness.js CHANGED
@@ -7,7 +7,7 @@ const cp = require('child_process');
7
7
  const os = require('os'); // 1.9.178: _publishToNpm μ—μ„œ os.tmpdir() μ‚¬μš© (μ „μ—­ import)
8
8
  const readline = require('readline');
9
9
 
10
- const VERSION = '1.9.231';
10
+ const VERSION = '1.9.232';
11
11
 
12
12
  // 1.9.184: DEP0190 (child_process shell: true) deprecation warning μ–΅μ œ (μ‚¬μš©μž λͺ…μ‹œ).
13
13
  // leerness λŠ” cross-platform PATH resolution 을 μœ„ν•΄ shell: true λ₯Ό μ˜λ„μ μœΌλ‘œ μ‚¬μš© (claude.cmd / ollama.cmd λ“± Windows .cmd 처리).
@@ -2227,14 +2227,22 @@ function pulseCmd(root) {
2227
2227
  const matches = src.match(/name: 'leerness_[a-z_]+'/g) || [];
2228
2228
  data.mcpTools = matches.length;
2229
2229
  } catch {}
2230
- // Memory Surface (T/D/R/P/L)
2230
+ // Memory Surface (T/D/R/P/L) β€” 1.9.232 BUG fix: memoryStatusCmd 와 λ™μΌν•œ νŒ¨ν„΄ μ‚¬μš©
2231
2231
  try {
2232
- const tasks = (read(progressTrackerPath(root)).split('\n').filter(l => /\|\s*in-progress\s*\|/.test(l)) || []).length;
2233
- const decisions = ((read(path.join(root, '.harness', 'decisions.md')) || '').match(/^##\s/gm) || []).length;
2234
- const rules = readRules(root).filter(r => r.status === 'active').length;
2235
- const milestonesCnt = ((read(path.join(root, '.harness', 'plan.md')) || '').match(/^- M-\d+/gm) || []).length;
2236
- const lessons = ((read(path.join(root, '.harness', 'lessons.md')) || '').match(/^###\s/gm) || []).length;
2237
- data.memorySurface = `T${tasks}/D${decisions}/R${rules}/P${milestonesCnt}/L${lessons}`;
2232
+ const rows = readProgressRows(root);
2233
+ const tasksInProgress = rows.filter(r => r.status === 'in-progress').length;
2234
+ const dm = exists(decisionsPath(root)) ? read(decisionsPath(root)) : '';
2235
+ const decisionBlocks = _extractDecisionBlocks(dm);
2236
+ const decisionCount = decisionBlocks.map(b => {
2237
+ const m = b.match(/^### (.+)$/m);
2238
+ return m ? '### ' + m[1].trim() : null;
2239
+ }).filter(Boolean).length;
2240
+ const rulesActive = readRules(root).filter(r => r.status === 'active').length;
2241
+ const planText = exists(planPath(root)) ? read(planPath(root)) : '';
2242
+ const milestonesCnt = (planText.match(/^### M-\d{4}\./gm) || []).length;
2243
+ const lm = exists(lessonsPath(root)) ? read(lessonsPath(root)) : '';
2244
+ const lessonsCount = (lm.match(/^### \d{4}-\d{2}-\d{2}[^\n]*/gm) || []).length;
2245
+ data.memorySurface = `T${tasksInProgress}/D${decisionCount}/R${rulesActive}/P${milestonesCnt}/L${lessonsCount}`;
2238
2246
  } catch {}
2239
2247
  // λ§ˆμΌμŠ€ν†€ + ETA
2240
2248
  try {
@@ -2263,7 +2271,7 @@ function pulseCmd(root) {
2263
2271
  if (data.abnormalShutdown !== 'none') {
2264
2272
  line += ` Β· πŸ”Œ abnormal:${data.abnormalShutdown}`;
2265
2273
  }
2266
- log(cy(`# leerness pulse (1.9.231) β€” ν•œ 쀄 μ’…ν•© μš”μ•½`));
2274
+ log(cy(`# leerness pulse (1.9.231/1.9.232) β€” ν•œ 쀄 μ’…ν•© μš”μ•½`));
2267
2275
  log('');
2268
2276
  log(` ${line}`);
2269
2277
  log('');
@@ -7265,6 +7273,10 @@ function _handoffWorkspace(rootBase) {
7265
7273
  }
7266
7274
 
7267
7275
  function handoffCmd(root) {
7276
+ // 1.9.232: --pulse μ˜΅μ…˜ β€” pulse 1 line ν˜•μ‹μœΌλ‘œ 좜λ ₯ (handoff 전체 λŒ€μ‹ )
7277
+ if (has('--pulse')) {
7278
+ return pulseCmd(absRoot(root));
7279
+ }
7268
7280
  // 1.9.17: --all-apps / --include 톡합 λͺ¨λ“œ
7269
7281
  if (has('--all-apps') || arg('--include', null)) {
7270
7282
  return _handoffWorkspace(absRoot(root));
@@ -10349,6 +10361,28 @@ function sessionClose(root, opts = {}) {
10349
10361
  log(grn(` βœ“ λ©±λ“±μ„± 검사 톡과 β€” verified ${idemp.summary.verifiedAreas} μ˜μ—­`));
10350
10362
  }
10351
10363
  } catch {}
10364
+ // 1.9.232: 마감 μ‹œ pulse ν•œ 쀄 μžλ™ λ…ΈμΆœ β€” λ‹€μŒ λΌμš΄λ“œ μ§„μž… μ‹œ μ¦‰μ‹œ μƒνƒœ 인지
10365
+ try {
10366
+ const rh = _computeRoundHistory(root);
10367
+ const ms = _computeMilestones(root);
10368
+ const rows = readProgressRows(root);
10369
+ const tIn = rows.filter(r => r.status === 'in-progress').length;
10370
+ const dm = exists(decisionsPath(root)) ? read(decisionsPath(root)) : '';
10371
+ const dCnt = _extractDecisionBlocks(dm).length;
10372
+ const rActive = readRules(root).filter(r => r.status === 'active').length;
10373
+ const planText = exists(planPath(root)) ? read(planPath(root)) : '';
10374
+ const pCnt = (planText.match(/^### M-\d{4}\./gm) || []).length;
10375
+ const lm = exists(lessonsPath(root)) ? read(lessonsPath(root)) : '';
10376
+ const lCnt = (lm.match(/^### \d{4}-\d{2}-\d{2}[^\n]*/gm) || []).length;
10377
+ const mem = `T${tIn}/D${dCnt}/R${rActive}/P${pCnt}/L${lCnt}`;
10378
+ let pulseLine = `πŸ“ v${VERSION} Β· πŸ”„ R${rh.roundCount} Β· 🧠 ${mem}`;
10379
+ if (ms.next) {
10380
+ const eta = ms.next.etaDays != null ? ` (${ms.next.etaDays}d)` : '';
10381
+ pulseLine += ` · 🎯 R${ms.next.milestone}${eta}`;
10382
+ }
10383
+ log('');
10384
+ log(` ${pulseLine} ${dim('β€” leerness pulse (1.9.232)')}`);
10385
+ } catch {}
10352
10386
  } catch {}
10353
10387
  }
10354
10388
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "leerness",
3
- "version": "1.9.231",
3
+ "version": "1.9.232",
4
4
  "description": "Leerness: λΉ„νŒŒκ΄΄ λ§ˆμ΄κ·Έλ ˆμ΄μ…˜, μžλ™ 버전 κ°μ§€Β·μ—…λ°μ΄νŠΈ, κ³„νš/μ§„ν–‰/ν•Έλ“œμ˜€ν”„ μžλ™ν™”, κ²ŒμœΌλ¦„Β·μ‹œν¬λ¦ΏΒ·μΈμ½”λ”© μžλ™ κ°€λ“œ, Claude Code μŠ¬λž˜μ‹œ 톡합을 κ°–μΆ˜ ν•œκ΅­μ–΄ μš°μ„  AI 개발 ν•˜λ„€μŠ€.",
5
5
  "keywords": [
6
6
  "leerness",