leerness 1.9.225 β 1.9.226
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 +37 -0
- package/README.md +3 -3
- package/bin/harness.js +98 -2
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,42 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.9.226 β 2026-05-23
|
|
4
|
+
|
|
5
|
+
**π round-history CLI + handoff ν€λλΌμΈ λΌμ΄λ μΉ΄μ΄ν° + MCP 62λ²μ§Έ λꡬ.**
|
|
6
|
+
|
|
7
|
+
### 1. `leerness round-history` μ λͺ
λ Ή β μμ¨ λΌμ΄λ ν΅κ³
|
|
8
|
+
- git tag `v1.9.X` κΈ°λ° λμ λΌμ΄λ μΉ΄μ΄νΈ (graceful fallback: git μμΌλ©΄ 0)
|
|
9
|
+
- μλ΅: `{ currentVersion, roundCount, baselineVersion, latestTags[], nextMilestone, roundsToNextMilestone, firstTagAt, latestTagAt, daysActive, avgRoundsPerDay }`
|
|
10
|
+
- λ§μΌμ€ν€ μλ κ°μ§: 50/75/100/125/150/175/200/250/300/400/500
|
|
11
|
+
- `--json` μ΅μ
(μΈλΆ μλν)
|
|
12
|
+
|
|
13
|
+
### 2. handoff ν€λλΌμΈ 17λ²μ§Έ μμ
|
|
14
|
+
- 5 λΌμ΄λ μ΄μ λμ μ `π R<N>` μλ λ
ΈμΆ
|
|
15
|
+
- λ€μ λ§μΌμ€ν€μ΄ 20 λΌμ΄λ μ΄λ΄μΌ λ: `π R182 β R200 (18R λ¨μ)` κ°μ‘°
|
|
16
|
+
- μμ¨ λͺ¨λ μ§νλ νλμ
|
|
17
|
+
|
|
18
|
+
### 3. MCP 62λ²μ§Έ λꡬ β `leerness_round_history`
|
|
19
|
+
- μΈλΆ AIκ° "μ΄ νλ‘μ νΈλ μΌλ§λ μ§νλκ³ λ€μ λ§μΌμ€ν€κΉμ§ λͺ λΌμ΄λ λ¨μλ?"λ₯Ό νμ
|
|
20
|
+
- MCP 61 β 62 (+1)
|
|
21
|
+
|
|
22
|
+
### 4. μ€ μΈ‘μ (leerness μ체 νλ‘μ νΈ)
|
|
23
|
+
- λμ λΌμ΄λ: **182R** (baseline v1.9.6 β v1.9.225)
|
|
24
|
+
- νλ κΈ°κ°: 14μΌ / νκ· **13 rounds/day**
|
|
25
|
+
- λ€μ λ§μΌμ€ν€: **R200 (18 λΌμ΄λ λ¨μ)**
|
|
26
|
+
|
|
27
|
+
### 5. λμ νκ· (1.9.207~225) β λͺ¨λ μ μ§
|
|
28
|
+
|
|
29
|
+
### 6. stress-v171 β 16/16 PASS
|
|
30
|
+
- 1.9.226 (7): VERSION + round-history CLI + --json + git μλ fallback + handoff ν€λλΌμΈ + MCP 62 λ±λ‘ + MCP μ€ νΈμΆ
|
|
31
|
+
- μ±λ₯ (2): cold_start avg 336ms / round-history 535ms
|
|
32
|
+
- λμ νκ· (7): 1.9.207~225
|
|
33
|
+
|
|
34
|
+
### 7. μλ release (88 λΌμ΄λ main-push streak Β· 49 λΌμ΄λ npm publish streak)
|
|
35
|
+
|
|
36
|
+
π **μμ¨ λΌμ΄λ μ§νλ κ°μν** β handoff ν μ€μμ λ§μΌμ€ν€ μμΈ‘ κ°λ₯
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
3
40
|
## 1.9.225 β 2026-05-22
|
|
4
41
|
|
|
5
42
|
**π§ drift check --auto-fix delivered ν΅ν© + LEERNESS_AUTO_APPLY_DELIVERED env opt-in.**
|
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
> **AI μ½λ© μμ΄μ νΈμ κ±°μ§ μλ£Β·μ€λ³΅Β·λ§κ°Β·μΆ©λμ λ§μμ£Όλ κ²μΒ·κΈ°μ΅Β·νμ
CLI νλ€μ€.**
|
|
4
4
|
|
|
5
|
-
[](https://www.npmjs.com/package/leerness) [](https://www.npmjs.com/package/leerness) []() []() []() []() []() []() [-brightgreen)]() []() []() []() []() []()
|
|
6
6
|
|
|
7
7
|
```
|
|
8
8
|
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
@@ -12,9 +12,9 @@
|
|
|
12
12
|
β βββ ββββββ ββββββ ββββββββββββββββββββββββ ββββββββ β
|
|
13
13
|
β βββββββββββββββββββββββββββ ββββββ ββββββββββββββββββββββ β
|
|
14
14
|
β βββββββββββββββββββββββββββ ββββββ βββββββββββββββββββββ β
|
|
15
|
-
β v1.9.
|
|
15
|
+
β v1.9.226 AI Agent Reliability Harness + Sandbox β
|
|
16
16
|
β verify Β· remember Β· orchestrate Β· audit Β· sandbox Β· drift β
|
|
17
|
-
β
|
|
17
|
+
β π round-history CLI + handoff R182 β R200 λ§μΌμ€ν€ β
|
|
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.
|
|
10
|
+
const VERSION = '1.9.226';
|
|
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 μ²λ¦¬).
|
|
@@ -2054,6 +2054,84 @@ function _compareSemver(a, b) {
|
|
|
2054
2054
|
return 0;
|
|
2055
2055
|
}
|
|
2056
2056
|
|
|
2057
|
+
// 1.9.226: round-history β git tag v1.9.X κΈ°λ° μμ¨ λΌμ΄λ ν΅κ³ + λ€μ λ§μΌμ€ν€
|
|
2058
|
+
// gitμ΄ μκ±°λ tagκ° μμΌλ©΄ graceful fallback (current version + 0 history)
|
|
2059
|
+
// μλ΅: { currentVersion, roundCount, baselineVersion, latestTags[], nextMilestone, roundsToNextMilestone, firstTagAt, latestTagAt, daysActive, avgRoundsPerDay }
|
|
2060
|
+
function _computeRoundHistory(root) {
|
|
2061
|
+
const result = {
|
|
2062
|
+
currentVersion: VERSION,
|
|
2063
|
+
roundCount: 0,
|
|
2064
|
+
baselineVersion: null,
|
|
2065
|
+
latestTags: [],
|
|
2066
|
+
nextMilestone: null,
|
|
2067
|
+
roundsToNextMilestone: null,
|
|
2068
|
+
firstTagAt: null,
|
|
2069
|
+
latestTagAt: null,
|
|
2070
|
+
daysActive: 0,
|
|
2071
|
+
avgRoundsPerDay: 0
|
|
2072
|
+
};
|
|
2073
|
+
try {
|
|
2074
|
+
// git tag --list 'v1.9.*' --sort=creatordate (μκ°μ)
|
|
2075
|
+
const r = cp.spawnSync('git', ['tag', '--list', 'v1.9.*', '--sort=creatordate', '--format=%(refname:short)|%(creatordate:iso8601)'], {
|
|
2076
|
+
cwd: root, encoding: 'utf8', timeout: 5000
|
|
2077
|
+
});
|
|
2078
|
+
if (r.status !== 0 || !r.stdout) return result;
|
|
2079
|
+
const lines = r.stdout.split('\n').filter(l => l.trim() && /^v\d+\.\d+\.\d+\|/.test(l));
|
|
2080
|
+
if (lines.length === 0) return result;
|
|
2081
|
+
const tags = lines.map(l => {
|
|
2082
|
+
const [name, date] = l.split('|');
|
|
2083
|
+
return { name: name.trim(), version: name.replace(/^v/, '').trim(), date: date.trim() };
|
|
2084
|
+
});
|
|
2085
|
+
result.roundCount = tags.length;
|
|
2086
|
+
result.baselineVersion = tags[0].version;
|
|
2087
|
+
result.firstTagAt = tags[0].date;
|
|
2088
|
+
result.latestTagAt = tags[tags.length - 1].date;
|
|
2089
|
+
// μ΅κ·Ό 10κ°
|
|
2090
|
+
result.latestTags = tags.slice(-10).reverse().map(t => ({ version: t.version, date: t.date.split('T')[0] }));
|
|
2091
|
+
// λ€μ λ§μΌμ€ν€ (50/100/150/200/300/...)
|
|
2092
|
+
const milestones = [50, 75, 100, 125, 150, 175, 200, 250, 300, 400, 500];
|
|
2093
|
+
const next = milestones.find(m => m > result.roundCount);
|
|
2094
|
+
if (next != null) {
|
|
2095
|
+
result.nextMilestone = next;
|
|
2096
|
+
result.roundsToNextMilestone = next - result.roundCount;
|
|
2097
|
+
}
|
|
2098
|
+
// μΌμΌ νκ·
|
|
2099
|
+
const first = new Date(result.firstTagAt).getTime();
|
|
2100
|
+
const last = new Date(result.latestTagAt).getTime();
|
|
2101
|
+
const days = Math.max(1, Math.floor((last - first) / 86400000));
|
|
2102
|
+
result.daysActive = days;
|
|
2103
|
+
result.avgRoundsPerDay = Math.round((result.roundCount / days) * 100) / 100;
|
|
2104
|
+
} catch {}
|
|
2105
|
+
return result;
|
|
2106
|
+
}
|
|
2107
|
+
|
|
2108
|
+
function roundHistoryCmd(root) {
|
|
2109
|
+
root = absRoot(root);
|
|
2110
|
+
const isTty = process.stdout && process.stdout.isTTY;
|
|
2111
|
+
const cy = s => isTty ? `\x1b[36m${s}\x1b[0m` : s;
|
|
2112
|
+
const gr = s => isTty ? `\x1b[32m${s}\x1b[0m` : s;
|
|
2113
|
+
const yl = s => isTty ? `\x1b[33m${s}\x1b[0m` : s;
|
|
2114
|
+
const dm = s => isTty ? `\x1b[2m${s}\x1b[0m` : s;
|
|
2115
|
+
const data = _computeRoundHistory(root);
|
|
2116
|
+
if (has('--json')) { log(JSON.stringify(data, null, 2)); return; }
|
|
2117
|
+
log(cy(`# leerness round-history (1.9.226) β μμ¨ λΌμ΄λ ν΅κ³`));
|
|
2118
|
+
log('');
|
|
2119
|
+
log(` π¦ νμ¬ λ²μ : ${gr(data.currentVersion)}`);
|
|
2120
|
+
log(` π λμ λΌμ΄λ: ${gr(String(data.roundCount))}`);
|
|
2121
|
+
if (data.baselineVersion) log(` π baseline: v${data.baselineVersion} (${(data.firstTagAt || '').split('T')[0]})`);
|
|
2122
|
+
if (data.latestTagAt) log(` β° μ΅κ·Ό tag: ${(data.latestTagAt || '').split('T')[0]}`);
|
|
2123
|
+
if (data.daysActive > 0) log(` π νλ: ${data.daysActive}μΌ / νκ· ${gr(data.avgRoundsPerDay + ' rounds/day')}`);
|
|
2124
|
+
log('');
|
|
2125
|
+
if (data.nextMilestone != null) {
|
|
2126
|
+
log(yl(` π― λ€μ λ§μΌμ€ν€: R${data.nextMilestone} (${data.roundsToNextMilestone} λΌμ΄λ λ¨μ)`));
|
|
2127
|
+
} else {
|
|
2128
|
+
log(gr(` π λͺ¨λ λ§μΌμ€ν€ λ¬μ± (500+)`));
|
|
2129
|
+
}
|
|
2130
|
+
log('');
|
|
2131
|
+
log(` μ΅κ·Ό 10 tags:`);
|
|
2132
|
+
data.latestTags.forEach(t => log(` β’ v${t.version} (${t.date})`));
|
|
2133
|
+
}
|
|
2134
|
+
|
|
2057
2135
|
// 1.9.208: νλ«νΌ/API μ μ½ μ¬μ μ²΄ν¬ (μ¬μ©μ λͺ
μ)
|
|
2058
2136
|
// "μ¬μ©μμ λͺ
λ Ήμ λ°μΌλ©΄, κ³ λ €ν΄μΌνλ λΆλΆμ λ¨Όμ νμΈνκ³ μ§ννκ² νλ©΄ μ΄λ¨μ§"
|
|
2059
2137
|
// "νΉμ νλ«νΌμ API ... νΈμΆμλκ° μ΄λΉ 5ν μ΄νλ‘λ§ ν΄μΌνλ€λ κ·μ μ λ¨Όμ νμΈ"
|
|
@@ -5987,6 +6065,17 @@ function handoff(root) {
|
|
|
5987
6065
|
parts.push(`π official ${m.total}/${m.cacheTotal} (${ageStr}${status})`);
|
|
5988
6066
|
}
|
|
5989
6067
|
} catch {}
|
|
6068
|
+
// 17) 1.9.226: round-history ν€λλΌμΈ β μμ¨ λΌμ΄λ μΉ΄μ΄ν° + λ€μ λ§μΌμ€ν€ (5 λΌμ΄λ μ΄μ μλ§ νμ)
|
|
6069
|
+
try {
|
|
6070
|
+
const rh = _computeRoundHistory(root);
|
|
6071
|
+
if (rh.roundCount >= 5) {
|
|
6072
|
+
let label = `π R${rh.roundCount}`;
|
|
6073
|
+
if (rh.nextMilestone != null && rh.roundsToNextMilestone <= 20) {
|
|
6074
|
+
label += ` β R${rh.nextMilestone} (${rh.roundsToNextMilestone}R λ¨μ)`;
|
|
6075
|
+
}
|
|
6076
|
+
parts.push(label);
|
|
6077
|
+
}
|
|
6078
|
+
} catch {}
|
|
5990
6079
|
// 12) 1.9.204: μλ λͺ¨λ νμ± νμ (μ¬μ©μ λͺ
μ) β R-0001 every-round λ£° νμ± μ ν€λλΌμΈ λ
ΈμΆ
|
|
5991
6080
|
try {
|
|
5992
6081
|
const autoRule = _getAutoLoopRule(root);
|
|
@@ -13889,7 +13978,8 @@ function mcpServeCmd(root) {
|
|
|
13889
13978
|
{ name: 'leerness_intent_classify', description: '1.9.216 (1.9.213 μ¬μ©μ λͺ
μ) β μ¬μ©μ μλ νμ
+ scope expansion κ²μ΄νΈ. μλ΅: { intent: precise|broad|default, signals, domain, explicitMentions, expansionCandidates, mode: dry-run }. 3μμΉ μμ : (1) Always-Off Opt-In, (2) Dry-run κΈ°λ³Έ (μ€ν X), (3) λͺ
μ vs μΆλ‘ λΆλ¦¬ λΌλ²¨λ§. 5 λλ©μΈ (game/web/api/cli/data). μΈλΆ AIκ° "μ΄ μμ²μ μ νν κ·Έκ²λ§ / ν¬κ΄μ / κΈ°λ³ΈμΈκ°?"λ₯Ό νμ. μΈμ: { request (required), path? }', inputSchema: { type: 'object', properties: { request: { type: 'string' }, path: { type: 'string' } }, required: ['request'] } },
|
|
13890
13979
|
{ name: 'leerness_idempotency_audit', description: '1.9.216 (1.9.212 μ¬μ©μ λͺ
μ) β λ©±λ±μ± μλ° νμ§. 4μμ μ κ²: rule-duplicate (medium) / task-duplicate-request (medium) / user-request-duplicate (low) / wakeup-duplicate (high). μλ΅: { violations[], verified[], summary: {totalViolations, high/medium/low, overall} }. μΈλΆ AIκ° "μν¬μ€νμ΄μ€μ μ€λ³΅/μΆ©λμ΄ μλ?"λ₯Ό νμ. π MCP 58 λꡬ λ§μΌμ€ν€ (50β58). μΈμ: { path? }', inputSchema: { type: 'object', properties: { path: { type: 'string' } } } },
|
|
13891
13980
|
{ name: 'leerness_session_resume', description: '1.9.221 (1.9.220 μ¬μ©μ λͺ
μ) β λΉμ μ μ’
λ£ κ°μ§ + μμ¨ μ¬κ°. 5μ νΈ λΆμ: last-handoff-stale / wakeup-missed / in-progress-stale / auto-resume-plan-unused / release-branch-pending. μλ΅: { abnormalShutdown, severity (none/low/medium/high), signals[], resumeGuide[] }. μΈλΆ AIκ° "μ μ /μμ€ν
μ’
λ£/μΈμ
μ’
λ£ ν leerness μνκ° μ μμΈκ°? μ΄λ»κ² μ¬κ°?"λ₯Ό νμ. π MCP 60 λꡬ λ§μΌμ€ν€ (53β60, +7 in 1.9.168/216/221). μΈμ: { path? }', inputSchema: { type: 'object', properties: { path: { type: 'string' } } } },
|
|
13892
|
-
{ name: 'leerness_requests_auto_complete', description: '1.9.224 (1.9.223 μλ νμ) β delivered ν¨ν΄ μλ κ°μ§ + μλ μλ£. "Round X.Y.Z β ꡬν μλ£" / "implemented" / "delivered" ν¨ν΄μ΄ μλ open μμ² μ€ νμ¬ λ²μ μ΄νμΈ κ²μ νλ³΄λ‘ λΆλ₯. μλ΅: { total, candidates: [{id, text, claimedVersion, currentVersion, deliveredKeyword, recordedAt}], currentVersion, applied (apply=true μ), completedIds[] }. μΈλΆ AIκ° "μ΄μ λμ λ κ°μ§ λ―Έλ΅ μ νΈ μ 리 κ°λ₯νκ°?"λ₯Ό νμ. κΈ°λ³Έ dry-run, apply: true λͺ
μ μμλ§ μ€ μ μ©. μΈμ: { path?, apply? (default false) }', inputSchema: { type: 'object', properties: { path: { type: 'string' }, apply: { type: 'boolean' } } } }
|
|
13981
|
+
{ name: 'leerness_requests_auto_complete', description: '1.9.224 (1.9.223 μλ νμ) β delivered ν¨ν΄ μλ κ°μ§ + μλ μλ£. "Round X.Y.Z β ꡬν μλ£" / "implemented" / "delivered" ν¨ν΄μ΄ μλ open μμ² μ€ νμ¬ λ²μ μ΄νμΈ κ²μ νλ³΄λ‘ λΆλ₯. μλ΅: { total, candidates: [{id, text, claimedVersion, currentVersion, deliveredKeyword, recordedAt}], currentVersion, applied (apply=true μ), completedIds[] }. μΈλΆ AIκ° "μ΄μ λμ λ κ°μ§ λ―Έλ΅ μ νΈ μ 리 κ°λ₯νκ°?"λ₯Ό νμ. κΈ°λ³Έ dry-run, apply: true λͺ
μ μμλ§ μ€ μ μ©. μΈμ: { path?, apply? (default false) }', inputSchema: { type: 'object', properties: { path: { type: 'string' }, apply: { type: 'boolean' } } } },
|
|
13982
|
+
{ name: 'leerness_round_history', description: '1.9.226 β μμ¨ λΌμ΄λ ν΅κ³. git tag v1.9.X κΈ°λ° λμ λΌμ΄λ μΉ΄μ΄νΈ + λ€μ λ§μΌμ€ν€ (50/75/100/125/150/175/200/250/300/400/500) + νκ· rounds/day. μλ΅: { currentVersion, roundCount, baselineVersion, latestTags[], nextMilestone, roundsToNextMilestone, firstTagAt, latestTagAt, daysActive, avgRoundsPerDay }. μΈλΆ AIκ° "μ΄ νλ‘μ νΈλ μΌλ§λ μ§νλκ³ λ€μ λ§μΌμ€ν€κΉμ§ λͺ λΌμ΄λ λ¨μλ?"λ₯Ό νμ. μΈμ: { path? }', inputSchema: { type: 'object', properties: { path: { type: 'string' } } } }
|
|
13893
13983
|
];
|
|
13894
13984
|
|
|
13895
13985
|
function send(obj) {
|
|
@@ -14050,6 +14140,10 @@ function mcpServeCmd(root) {
|
|
|
14050
14140
|
cliArgs = ['requests', 'auto-complete', '--path', targetPath, '--json'];
|
|
14051
14141
|
if (args.apply === true) cliArgs.push('--apply');
|
|
14052
14142
|
break;
|
|
14143
|
+
case 'leerness_round_history':
|
|
14144
|
+
// 1.9.226: μμ¨ λΌμ΄λ ν΅κ³ + λ€μ λ§μΌμ€ν€
|
|
14145
|
+
cliArgs = ['round-history', '--path', targetPath, '--json'];
|
|
14146
|
+
break;
|
|
14053
14147
|
default:
|
|
14054
14148
|
return send({ jsonrpc: '2.0', id, error: { code: -32601, message: `Unknown tool: ${name}` } });
|
|
14055
14149
|
}
|
|
@@ -17681,6 +17775,8 @@ async function main() {
|
|
|
17681
17775
|
if (cmd === 'requests') return requestsCmd(arg('--path', process.cwd()), args[1], ...args.slice(2));
|
|
17682
17776
|
// 1.9.220: leerness session-resume β λΉμ μ μ’
λ£ κ°μ§ + μμ¨ μ¬κ° κ°μ΄λ (μ¬μ©μ λͺ
μ)
|
|
17683
17777
|
if (cmd === 'session-resume') return sessionResumeCmd(arg('--path', process.cwd()));
|
|
17778
|
+
// 1.9.226: leerness round-history β μμ¨ λΌμ΄λ ν΅κ³ + λ€μ λ§μΌμ€ν€
|
|
17779
|
+
if (cmd === 'round-history') return roundHistoryCmd(arg('--path', process.cwd()));
|
|
17684
17780
|
// 1.9.208: leerness constraints <list|check|add> β νλ«νΌ/API μ μ½ μ¬μ μ²΄ν¬ (μ¬μ©μ λͺ
μ)
|
|
17685
17781
|
if (cmd === 'constraints') return constraintsCmd(arg('--path', process.cwd()), args[1], ...args.slice(2));
|
|
17686
17782
|
// 1.9.209: leerness pre-wake-audit β sleep μ sub-agent audit (μ¬μ©μ λͺ
μ)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "leerness",
|
|
3
|
-
"version": "1.9.
|
|
3
|
+
"version": "1.9.226",
|
|
4
4
|
"description": "Leerness: λΉνκ΄΄ λ§μ΄κ·Έλ μ΄μ
, μλ λ²μ κ°μ§Β·μ
λ°μ΄νΈ, κ³ν/μ§ν/νΈλμ€ν μλν, κ²μΌλ¦Β·μν¬λ¦ΏΒ·μΈμ½λ© μλ κ°λ, Claude Code μ¬λμ ν΅ν©μ κ°μΆ νκ΅μ΄ μ°μ AI κ°λ° νλ€μ€.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"leerness",
|