leerness 1.9.228 β 1.9.229
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 +38 -0
- package/README.md +3 -3
- package/bin/harness.js +100 -2
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,43 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.9.229 β 2026-05-23
|
|
4
|
+
|
|
5
|
+
**π― leerness milestones CLI + MCP 63λ²μ§Έ λꡬ (λλ¬ λ§μΌμ€ν€ + ETA μμΈ‘).**
|
|
6
|
+
|
|
7
|
+
### 1. `leerness milestones` μ λͺ
λ Ή
|
|
8
|
+
- git tag μμ°¨ λΆμμΌλ‘ 25/50/75/100/125/150/175/200/250/300/400/500 λ§μΌμ€ν€ λλ¬ μμ νμ
|
|
9
|
+
- κ° λ§μΌμ€ν€λ³: `{milestone, version, reachedAt, daysFromBaseline}`
|
|
10
|
+
- λ€μ λ§μΌμ€ν€ ETA κ³μ° (νμ¬ μλ κΈ°μ€): `{milestone, roundsRemaining, etaDays, etaDate}`
|
|
11
|
+
- `--json` μ΅μ
|
|
12
|
+
- 1.9.226 round-history νμ₯ (κ°λ¨ ν΅κ³ β λλ¬ μ΄λ ₯ + ETA)
|
|
13
|
+
|
|
14
|
+
### 2. MCP 63λ²μ§Έ λꡬ β `leerness_milestones`
|
|
15
|
+
- μΈλΆ AIκ° "νλ‘μ νΈ λ§μΌμ€ν€ μ§μ²λ + λ€μ λ¬μ± μμμΌ" μ§μ νμ
|
|
16
|
+
- MCP 62 β 63 (+1)
|
|
17
|
+
|
|
18
|
+
### 3. μ€ μΈ‘μ β leerness μ체 λ§μΌμ€ν€ μ΄λ ₯ (7κ° λ¬μ±)
|
|
19
|
+
- R25 β v1.9.68 (2026-05-19, +11d)
|
|
20
|
+
- R50 β v1.9.93 (2026-05-20, +11d)
|
|
21
|
+
- R75 β v1.9.118 (2026-05-20, +11d)
|
|
22
|
+
- R100 β v1.9.143 (2026-05-20, +11d)
|
|
23
|
+
- R125 β v1.9.168 (2026-05-20, +12d)
|
|
24
|
+
- R150 β v1.9.193 (2026-05-21, +12d)
|
|
25
|
+
- R175 β v1.9.218 (2026-05-22, +14d)
|
|
26
|
+
- **λ€μ: R200** β 2026-05-24 ETA (15 λΌμ΄λ λ¨μ, ~2μΌ ν)
|
|
27
|
+
|
|
28
|
+
### 4. λμ νκ· (1.9.207~228) β λͺ¨λ μ μ§
|
|
29
|
+
|
|
30
|
+
### 5. stress-v174 β 17/17 PASS
|
|
31
|
+
- 1.9.229 (7): VERSION + CLI + reached νν + next ETA + git fallback + MCP 63 + μ€ νΈμΆ
|
|
32
|
+
- μ±λ₯ (2): cold_start avg 442ms / milestones 717ms
|
|
33
|
+
- λμ νκ· (8): 1.9.207~228
|
|
34
|
+
|
|
35
|
+
### 6. μλ release (91 λΌμ΄λ main-push streak Β· 52 λΌμ΄λ npm publish streak)
|
|
36
|
+
|
|
37
|
+
π― **μμ¨ λͺ¨λ μ§μ²λ μκ°ν μμ±** β λλ¬ μ΄λ ₯ + μμΈ‘ ETA λͺ¨λ κ°μν
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
3
41
|
## 1.9.228 β 2026-05-23
|
|
4
42
|
|
|
5
43
|
**π health --json roundHistory ν΅ν© (JSON 3 λͺ
λ Ή μΌκ΄μ±) + session-workflow.md drift μ°¨λ¨ + ν€λλΌμΈ label κ°±μ .**
|
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.229 AI Agent Reliability Harness + Sandbox β
|
|
16
16
|
β verify Β· remember Β· orchestrate Β· audit Β· sandbox Β· drift β
|
|
17
|
-
β
|
|
17
|
+
β π― milestones CLI Β· MCP 63 Β· λλ¬ μ΄λ ₯ + ETA μμΈ‘ β
|
|
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.229';
|
|
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 μ²λ¦¬).
|
|
@@ -2105,6 +2105,97 @@ function _computeRoundHistory(root) {
|
|
|
2105
2105
|
return result;
|
|
2106
2106
|
}
|
|
2107
2107
|
|
|
2108
|
+
// 1.9.229: milestones β λλ¬ν λ§μΌμ€ν€ μΌμ + λ€μ λ§μΌμ€ν€ μμ μμ (1.9.226 round-history νμ₯)
|
|
2109
|
+
// git tag μμ°¨ λΆμ β 50/75/100/... λλ¬ μμ μ tag μ μΌμ νμ
|
|
2110
|
+
// μλ΅: { reached: [{milestone, version, reachedAt, daysFromBaseline}], next: {milestone, roundsRemaining, eta}, totalRounds, avgRoundsPerDay }
|
|
2111
|
+
function _computeMilestones(root) {
|
|
2112
|
+
const result = {
|
|
2113
|
+
totalRounds: 0,
|
|
2114
|
+
reached: [],
|
|
2115
|
+
next: null,
|
|
2116
|
+
avgRoundsPerDay: 0,
|
|
2117
|
+
baselineAt: null
|
|
2118
|
+
};
|
|
2119
|
+
try {
|
|
2120
|
+
const r = cp.spawnSync('git', ['tag', '--list', 'v1.9.*', '--sort=creatordate', '--format=%(refname:short)|%(creatordate:iso8601)'], {
|
|
2121
|
+
cwd: root, encoding: 'utf8', timeout: 5000
|
|
2122
|
+
});
|
|
2123
|
+
if (r.status !== 0 || !r.stdout) return result;
|
|
2124
|
+
const lines = r.stdout.split('\n').filter(l => l.trim() && /^v\d+\.\d+\.\d+\|/.test(l));
|
|
2125
|
+
if (lines.length === 0) return result;
|
|
2126
|
+
const tags = lines.map(l => {
|
|
2127
|
+
const [name, date] = l.split('|');
|
|
2128
|
+
return { name: name.trim(), version: name.replace(/^v/, '').trim(), date: date.trim() };
|
|
2129
|
+
});
|
|
2130
|
+
result.totalRounds = tags.length;
|
|
2131
|
+
result.baselineAt = tags[0].date;
|
|
2132
|
+
const milestones = [25, 50, 75, 100, 125, 150, 175, 200, 250, 300, 400, 500];
|
|
2133
|
+
const baselineTime = new Date(tags[0].date).getTime();
|
|
2134
|
+
// 1-indexed: tags[0] is round 1
|
|
2135
|
+
for (const m of milestones) {
|
|
2136
|
+
if (m <= tags.length) {
|
|
2137
|
+
const t = tags[m - 1];
|
|
2138
|
+
const reachedTime = new Date(t.date).getTime();
|
|
2139
|
+
const daysFromBaseline = Math.floor((reachedTime - baselineTime) / 86400000);
|
|
2140
|
+
result.reached.push({
|
|
2141
|
+
milestone: m,
|
|
2142
|
+
version: t.version,
|
|
2143
|
+
reachedAt: t.date.split(' ')[0],
|
|
2144
|
+
daysFromBaseline
|
|
2145
|
+
});
|
|
2146
|
+
}
|
|
2147
|
+
}
|
|
2148
|
+
// λ€μ λ§μΌμ€ν€ + νκ· μλλ‘ ETA κ³μ°
|
|
2149
|
+
const lastTime = new Date(tags[tags.length - 1].date).getTime();
|
|
2150
|
+
const days = Math.max(1, Math.floor((lastTime - baselineTime) / 86400000));
|
|
2151
|
+
const avgPerDay = (tags.length / days);
|
|
2152
|
+
result.avgRoundsPerDay = Math.round(avgPerDay * 100) / 100;
|
|
2153
|
+
const nextM = milestones.find(m => m > tags.length);
|
|
2154
|
+
if (nextM != null) {
|
|
2155
|
+
const roundsRemaining = nextM - tags.length;
|
|
2156
|
+
const etaDays = avgPerDay > 0 ? Math.ceil(roundsRemaining / avgPerDay) : null;
|
|
2157
|
+
const etaDate = etaDays != null ? new Date(Date.now() + etaDays * 86400000).toISOString().split('T')[0] : null;
|
|
2158
|
+
result.next = { milestone: nextM, roundsRemaining, etaDays, etaDate };
|
|
2159
|
+
}
|
|
2160
|
+
} catch {}
|
|
2161
|
+
return result;
|
|
2162
|
+
}
|
|
2163
|
+
|
|
2164
|
+
function milestonesCmd(root) {
|
|
2165
|
+
root = absRoot(root);
|
|
2166
|
+
const isTty = process.stdout && process.stdout.isTTY;
|
|
2167
|
+
const cy = s => isTty ? `\x1b[36m${s}\x1b[0m` : s;
|
|
2168
|
+
const gr = s => isTty ? `\x1b[32m${s}\x1b[0m` : s;
|
|
2169
|
+
const yl = s => isTty ? `\x1b[33m${s}\x1b[0m` : s;
|
|
2170
|
+
const dm = s => isTty ? `\x1b[2m${s}\x1b[0m` : s;
|
|
2171
|
+
const data = _computeMilestones(root);
|
|
2172
|
+
if (has('--json')) { log(JSON.stringify(data, null, 2)); return; }
|
|
2173
|
+
log(cy(`# leerness milestones (1.9.229) β λλ¬ λ§μΌμ€ν€ + λ€μ ETA`));
|
|
2174
|
+
log('');
|
|
2175
|
+
log(` π¦ μ΄ λΌμ΄λ: ${gr(String(data.totalRounds))}`);
|
|
2176
|
+
if (data.baselineAt) log(` π baseline: ${(data.baselineAt || '').split(' ')[0]}`);
|
|
2177
|
+
if (data.avgRoundsPerDay) log(` π νκ· : ${gr(data.avgRoundsPerDay + ' rounds/day')}`);
|
|
2178
|
+
log('');
|
|
2179
|
+
if (data.reached.length === 0) {
|
|
2180
|
+
log(dm(` (λλ¬ λ§μΌμ€ν€ μμ β 첫 R25 λ§μΌμ€ν€ μ§ν μ€)`));
|
|
2181
|
+
} else {
|
|
2182
|
+
log(` λλ¬ λ§μΌμ€ν€ ${data.reached.length}κ°:`);
|
|
2183
|
+
for (const m of data.reached) {
|
|
2184
|
+
log(` β R${m.milestone} ${gr(`(v${m.version}, ${m.reachedAt}, +${m.daysFromBaseline}d)`)}`);
|
|
2185
|
+
}
|
|
2186
|
+
}
|
|
2187
|
+
log('');
|
|
2188
|
+
if (data.next) {
|
|
2189
|
+
log(yl(` π― λ€μ λ§μΌμ€ν€: R${data.next.milestone}`));
|
|
2190
|
+
log(` β’ ${data.next.roundsRemaining} λΌμ΄λ λ¨μ`);
|
|
2191
|
+
if (data.next.etaDays != null) {
|
|
2192
|
+
log(` β’ ETA: ${data.next.etaDate} (~${data.next.etaDays}μΌ ν, νμ¬ μλ κΈ°μ€)`);
|
|
2193
|
+
}
|
|
2194
|
+
} else {
|
|
2195
|
+
log(gr(` π λͺ¨λ λ§μΌμ€ν€ λ¬μ± (500+)`));
|
|
2196
|
+
}
|
|
2197
|
+
}
|
|
2198
|
+
|
|
2108
2199
|
function roundHistoryCmd(root) {
|
|
2109
2200
|
root = absRoot(root);
|
|
2110
2201
|
const isTty = process.stdout && process.stdout.isTTY;
|
|
@@ -14003,7 +14094,8 @@ function mcpServeCmd(root) {
|
|
|
14003
14094
|
{ 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' } } } },
|
|
14004
14095
|
{ 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' } } } },
|
|
14005
14096
|
{ 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' } } } },
|
|
14006
|
-
{ 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' } } } }
|
|
14097
|
+
{ 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' } } } },
|
|
14098
|
+
{ name: 'leerness_milestones', description: '1.9.229 (1.9.226 νμ₯) β λλ¬ λ§μΌμ€ν€ + λ€μ ETA. git tag μμ°¨ λΆμμΌλ‘ 25/50/75/100/125/150/175/200/250/300/400/500 λ§μΌμ€ν€ λλ¬ μΌμ + λ€μ λ§μΌμ€ν€ ETA (νμ¬ μλ κΈ°μ€) κ³μ°. μλ΅: { totalRounds, reached: [{milestone, version, reachedAt, daysFromBaseline}], next: {milestone, roundsRemaining, etaDays, etaDate}, baselineAt, avgRoundsPerDay }. μΈλΆ AIκ° "μ§κΈκΉμ§ μ΄λ€ λ§μΌμ€ν€μ μΈμ λ¬μ±νκ³ λ€μ λ§μΌμ€ν€ μμ λλ¬μΌμ?"μ νμ. μΈμ: { path? }', inputSchema: { type: 'object', properties: { path: { type: 'string' } } } }
|
|
14007
14099
|
];
|
|
14008
14100
|
|
|
14009
14101
|
function send(obj) {
|
|
@@ -14168,6 +14260,10 @@ function mcpServeCmd(root) {
|
|
|
14168
14260
|
// 1.9.226: μμ¨ λΌμ΄λ ν΅κ³ + λ€μ λ§μΌμ€ν€
|
|
14169
14261
|
cliArgs = ['round-history', '--path', targetPath, '--json'];
|
|
14170
14262
|
break;
|
|
14263
|
+
case 'leerness_milestones':
|
|
14264
|
+
// 1.9.229: λλ¬ λ§μΌμ€ν€ + λ€μ ETA
|
|
14265
|
+
cliArgs = ['milestones', '--path', targetPath, '--json'];
|
|
14266
|
+
break;
|
|
14171
14267
|
default:
|
|
14172
14268
|
return send({ jsonrpc: '2.0', id, error: { code: -32601, message: `Unknown tool: ${name}` } });
|
|
14173
14269
|
}
|
|
@@ -17813,6 +17909,8 @@ async function main() {
|
|
|
17813
17909
|
if (cmd === 'session-resume') return sessionResumeCmd(arg('--path', process.cwd()));
|
|
17814
17910
|
// 1.9.226: leerness round-history β μμ¨ λΌμ΄λ ν΅κ³ + λ€μ λ§μΌμ€ν€
|
|
17815
17911
|
if (cmd === 'round-history') return roundHistoryCmd(arg('--path', process.cwd()));
|
|
17912
|
+
// 1.9.229: leerness milestones β λλ¬ λ§μΌμ€ν€ + λ€μ ETA (1.9.226 νμ₯)
|
|
17913
|
+
if (cmd === 'milestones') return milestonesCmd(arg('--path', process.cwd()));
|
|
17816
17914
|
// 1.9.208: leerness constraints <list|check|add> β νλ«νΌ/API μ μ½ μ¬μ μ²΄ν¬ (μ¬μ©μ λͺ
μ)
|
|
17817
17915
|
if (cmd === 'constraints') return constraintsCmd(arg('--path', process.cwd()), args[1], ...args.slice(2));
|
|
17818
17916
|
// 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.229",
|
|
4
4
|
"description": "Leerness: λΉνκ΄΄ λ§μ΄κ·Έλ μ΄μ
, μλ λ²μ κ°μ§Β·μ
λ°μ΄νΈ, κ³ν/μ§ν/νΈλμ€ν μλν, κ²μΌλ¦Β·μν¬λ¦ΏΒ·μΈμ½λ© μλ κ°λ, Claude Code μ¬λμ ν΅ν©μ κ°μΆ νκ΅μ΄ μ°μ AI κ°λ° νλ€μ€.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"leerness",
|