leerness 1.9.238 β 1.9.239
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 +44 -0
- package/README.md +3 -3
- package/bin/harness.js +166 -2
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,49 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.9.239 β 2026-05-24
|
|
4
|
+
|
|
5
|
+
**π leerness py-check + π€ agent-mode + MCP 67/68 (μ¬μ©μ λͺ
μ UR-0013).**
|
|
6
|
+
|
|
7
|
+
### μ¬μ©μ λͺ
μ (UR-0013)
|
|
8
|
+
> *"leernessκ° mdλΏλ§ μλλΌ pyλ₯Ό ν¬ν¨ν νμ΄μ¬ μ€ν¬λ¦½νΈ λ±μ΄ ν¨μ¨μ μ΄λΌκ±°λ, μμ΄μ νΈ λͺ¨λλ₯Ό μν μ₯μΉ λ± λ ν¨μ¨μ μΌλ‘ μλν μ μλλ‘ κ΅¬ν"*
|
|
9
|
+
|
|
10
|
+
### 1. `leerness py-check` μ λͺ
λ Ή β Python νμΌ λΆμ
|
|
11
|
+
- μμ‘΄μ± 0, regex fallback (Node λ΄μ₯λ§)
|
|
12
|
+
- λΆμ: νμΌ μ / LOC / imports / functions / classes / TODO/FIXME
|
|
13
|
+
- Top 5 νμΌ (LOC κΈ°μ€)
|
|
14
|
+
- `--json` μ΅μ
(μΈλΆ μλν)
|
|
15
|
+
- `.harness` / `node_modules` / `venv` / `__pycache__` λ± μλ skip
|
|
16
|
+
- leerness κ° .md μΈμλ **.py μΈμ§** β λ€μ€ μΈμ΄ μν¬μ€νμ΄μ€ μ§μ
|
|
17
|
+
|
|
18
|
+
### 2. `leerness agent-mode <start|tick|stop>` β μμ¨ λͺ¨λ μ μ© ν΅ν©
|
|
19
|
+
- **start**: handoff + drift --auto-fix + session-resume --auto-fix (μ§μ
μλν)
|
|
20
|
+
- **tick**: pulse ν μ€ (λ§€ λΌμ΄λ κ°λ²Όμ)
|
|
21
|
+
- **stop**: session close --auto-apply-delivered --auto-cleanup-branches (λ§κ° ν΅ν©)
|
|
22
|
+
- AI μμ¨ λΌμ΄λ μ§μ
/λ§€ λΌμ΄λ/λ§κ°μ **1 λͺ
λ ΉμΌλ‘ μμΆ** β νΈμΆ λΉμ© μ κ°
|
|
23
|
+
|
|
24
|
+
### 3. MCP 67/68λ²μ§Έ λꡬ
|
|
25
|
+
- `leerness_py_check` β μΈλΆ AI κ° Python νλ©΄ λΆμ
|
|
26
|
+
- `leerness_agent_mode` β μΈλΆ AI κ° μμ¨ λͺ¨λ λ¨μΌ νΈμΆ
|
|
27
|
+
- MCP 66 β 68 (+2)
|
|
28
|
+
|
|
29
|
+
### 4. κ²μ¦ β μ€ Python νμΌ (격리)
|
|
30
|
+
- 2 νμΌ β 22 LOC / 4 imports / 4 funcs / 2 classes / 2 TODOs (μ ν νμ)
|
|
31
|
+
- 200 file limit μμ κ°λ + heavy dir skip
|
|
32
|
+
|
|
33
|
+
### 5. λμ νκ· (1.9.207~238) β λͺ¨λ μ μ§
|
|
34
|
+
|
|
35
|
+
### 6. stress-v184 β 18/18 PASS
|
|
36
|
+
- 1.9.239 (8): VERSION + py-check (격리/human/fallback) + agent-mode (help/tick) + MCP 68 + μ€ νΈμΆ
|
|
37
|
+
- μ±λ₯ (2): cold_start avg 372ms / py-check 387ms
|
|
38
|
+
- λμ νκ· (8): 1.9.207~238
|
|
39
|
+
|
|
40
|
+
### 7. μλ release (101 λΌμ΄λ main-push streak Β· 62 λΌμ΄λ npm publish streak)
|
|
41
|
+
|
|
42
|
+
π **leerness λ€μ€ μΈμ΄ μ§μ μ μ€** β .md β .md + .py (νμ₯ κ°λ₯ λ² μ΄μ€)
|
|
43
|
+
π€ **agent-mode ν΅ν©** β μμ¨ λͺ¨λ μ§μ
/λ§€λΌμ΄λ/λ§κ°μ 3 λͺ
λ ΉμΌλ‘ λ¨μΆ
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
3
47
|
## 1.9.238 β 2026-05-24
|
|
4
48
|
|
|
5
49
|
**π R100 main-push streak λ¬μ± + CLAUDE/AGENTS/session-workflow drift μ°¨λ¨ (1.9.228~237 9 λΌμ΄λ λμ ).**
|
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) []() []() []() []() []() []() []() []() []() []() []() []()
|
|
6
6
|
|
|
7
7
|
```
|
|
8
8
|
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
@@ -12,9 +12,9 @@
|
|
|
12
12
|
β βββ ββββββ ββββββ ββββββββββββββββββββββββ ββββββββ β
|
|
13
13
|
β βββββββββββββββββββββββββββ ββββββ ββββββββββββββββββββββ β
|
|
14
14
|
β βββββββββββββββββββββββββββ ββββββ βββββββββββββββββββββ β
|
|
15
|
-
β v1.9.
|
|
15
|
+
β v1.9.239 AI Agent Reliability Harness + Sandbox β
|
|
16
16
|
β verify Β· remember Β· orchestrate Β· audit Β· sandbox Β· drift β
|
|
17
|
-
β
|
|
17
|
+
β π py-check Β· π€ agent-mode Β· MCP 68 (μ¬μ©μ λͺ
μ UR-0013) β
|
|
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.239';
|
|
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 μ²λ¦¬).
|
|
@@ -2196,6 +2196,156 @@ function milestonesCmd(root) {
|
|
|
2196
2196
|
}
|
|
2197
2197
|
}
|
|
2198
2198
|
|
|
2199
|
+
// 1.9.239: Python νμΌ λΆμ (μ¬μ©μ λͺ
μ UR-0013) β μμ‘΄μ± 0 regex fallback
|
|
2200
|
+
// leerness κ° .md μΈμ .py νμ΄μ¬ μ€ν¬λ¦½νΈλ ν¨μ¨μ μΌλ‘ μΈμ§νλλ‘.
|
|
2201
|
+
// λΆμ: νμΌ μ / import μ / ν¨μ μ / class μ / 볡μ‘λ(approx LOC) / TODO/FIXME
|
|
2202
|
+
// μλ΅ (--json): { totalFiles, totalLOC, imports[], funcs[], classes[], complexity, todoCount }
|
|
2203
|
+
function _collectPyFiles(root, limit = 100) {
|
|
2204
|
+
const out = [];
|
|
2205
|
+
function walk(dir) {
|
|
2206
|
+
if (out.length >= limit) return;
|
|
2207
|
+
let entries;
|
|
2208
|
+
try { entries = fs.readdirSync(dir, { withFileTypes: true }); }
|
|
2209
|
+
catch { return; }
|
|
2210
|
+
for (const e of entries) {
|
|
2211
|
+
if (out.length >= limit) return;
|
|
2212
|
+
const fp = path.join(dir, e.name);
|
|
2213
|
+
if (e.isDirectory()) {
|
|
2214
|
+
// skip common heavy dirs
|
|
2215
|
+
if (/^(node_modules|\.git|__pycache__|\.harness|venv|\.venv|dist|build|_apps|_reports)$/.test(e.name)) continue;
|
|
2216
|
+
walk(fp);
|
|
2217
|
+
} else if (e.isFile() && /\.py$/i.test(e.name)) {
|
|
2218
|
+
out.push(fp);
|
|
2219
|
+
}
|
|
2220
|
+
}
|
|
2221
|
+
}
|
|
2222
|
+
walk(root);
|
|
2223
|
+
return out;
|
|
2224
|
+
}
|
|
2225
|
+
|
|
2226
|
+
function _analyzePyFile(fp) {
|
|
2227
|
+
let txt = '';
|
|
2228
|
+
try { txt = fs.readFileSync(fp, 'utf8'); } catch { return null; }
|
|
2229
|
+
const lines = txt.split('\n');
|
|
2230
|
+
const importRe = /^\s*(?:from\s+\S+\s+)?import\s+\S+/;
|
|
2231
|
+
const funcRe = /^\s*(?:async\s+)?def\s+(\w+)\s*\(/;
|
|
2232
|
+
const classRe = /^\s*class\s+(\w+)/;
|
|
2233
|
+
const todoRe = /#\s*(TODO|FIXME|XXX|HACK)\b/;
|
|
2234
|
+
let imports = 0, funcs = [], classes = [], todos = 0;
|
|
2235
|
+
for (const line of lines) {
|
|
2236
|
+
if (importRe.test(line)) imports++;
|
|
2237
|
+
const fm = line.match(funcRe); if (fm) funcs.push(fm[1]);
|
|
2238
|
+
const cm = line.match(classRe); if (cm) classes.push(cm[1]);
|
|
2239
|
+
if (todoRe.test(line)) todos++;
|
|
2240
|
+
}
|
|
2241
|
+
return {
|
|
2242
|
+
file: fp,
|
|
2243
|
+
loc: lines.length,
|
|
2244
|
+
imports,
|
|
2245
|
+
funcs: funcs.length,
|
|
2246
|
+
classes: classes.length,
|
|
2247
|
+
todos
|
|
2248
|
+
};
|
|
2249
|
+
}
|
|
2250
|
+
|
|
2251
|
+
function pyCheckCmd(root) {
|
|
2252
|
+
root = absRoot(root);
|
|
2253
|
+
const isTty = process.stdout && process.stdout.isTTY;
|
|
2254
|
+
const cy = s => isTty ? `\x1b[36m${s}\x1b[0m` : s;
|
|
2255
|
+
const gr = s => isTty ? `\x1b[32m${s}\x1b[0m` : s;
|
|
2256
|
+
const yl = s => isTty ? `\x1b[33m${s}\x1b[0m` : s;
|
|
2257
|
+
const dm = s => isTty ? `\x1b[2m${s}\x1b[0m` : s;
|
|
2258
|
+
const files = _collectPyFiles(root, 200);
|
|
2259
|
+
const analyses = files.map(f => _analyzePyFile(f)).filter(Boolean);
|
|
2260
|
+
const totalLOC = analyses.reduce((s, a) => s + a.loc, 0);
|
|
2261
|
+
const totalImports = analyses.reduce((s, a) => s + a.imports, 0);
|
|
2262
|
+
const totalFuncs = analyses.reduce((s, a) => s + a.funcs, 0);
|
|
2263
|
+
const totalClasses = analyses.reduce((s, a) => s + a.classes, 0);
|
|
2264
|
+
const totalTodos = analyses.reduce((s, a) => s + a.todos, 0);
|
|
2265
|
+
const result = {
|
|
2266
|
+
totalFiles: analyses.length,
|
|
2267
|
+
totalLOC, totalImports, totalFuncs, totalClasses, totalTodos,
|
|
2268
|
+
biggest: analyses.slice().sort((a, b) => b.loc - a.loc).slice(0, 5).map(a => ({ file: path.relative(root, a.file), loc: a.loc, funcs: a.funcs, classes: a.classes }))
|
|
2269
|
+
};
|
|
2270
|
+
if (has('--json')) { log(JSON.stringify(result, null, 2)); return; }
|
|
2271
|
+
log(cy(`# leerness py-check (1.9.239) β Python νμΌ λΆμ (μ¬μ©μ λͺ
μ UR-0013)`));
|
|
2272
|
+
log('');
|
|
2273
|
+
if (analyses.length === 0) {
|
|
2274
|
+
log(dm(` Python νμΌ μμ (.py κ²μλ¨: ${files.length}, λΆμ κ°λ₯: 0)`));
|
|
2275
|
+
log(dm(` β leerness λ .md/.py λͺ¨λ λΆμ κ°λ₯ (1.9.239)`));
|
|
2276
|
+
return;
|
|
2277
|
+
}
|
|
2278
|
+
log(` π ν΅κ³:`);
|
|
2279
|
+
log(` νμΌ ${gr(String(analyses.length))} Β· LOC ${gr(String(totalLOC))} Β· νκ· ${gr(String(Math.round(totalLOC / analyses.length)))} loc/file`);
|
|
2280
|
+
log(` imports ${totalImports} Β· functions ${totalFuncs} Β· classes ${totalClasses}`);
|
|
2281
|
+
if (totalTodos > 0) log(yl(` β TODO/FIXME ${totalTodos}건`));
|
|
2282
|
+
log('');
|
|
2283
|
+
if (result.biggest.length > 0) {
|
|
2284
|
+
log(` Top 5 νμΌ (LOC κΈ°μ€):`);
|
|
2285
|
+
result.biggest.forEach(f => log(` β’ ${f.file} β ${f.loc} loc / ${f.funcs} func / ${f.classes} class`));
|
|
2286
|
+
}
|
|
2287
|
+
log('');
|
|
2288
|
+
log(dm(` β JSON μΆλ ₯: leerness py-check --json`));
|
|
2289
|
+
}
|
|
2290
|
+
|
|
2291
|
+
// 1.9.239: agent-mode β μμ¨ λͺ¨λ μ μ© ν΅ν© λͺ
λ Ή (μ¬μ©μ λͺ
μ UR-0013)
|
|
2292
|
+
// handoff + pulse + drift auto-fix + session-resume λ₯Ό 1 λͺ
λ ΉμΌλ‘
|
|
2293
|
+
// start: μ§μ
(handoff + drift auto-fix + λΉμ μμ’
λ£ μλ ν볡)
|
|
2294
|
+
// tick: λ§€ λΌμ΄λ (pulse + 1 line)
|
|
2295
|
+
// stop: λ§κ° (session close + auto-apply-delivered + auto-cleanup-branches)
|
|
2296
|
+
function agentModeCmd(root, sub) {
|
|
2297
|
+
root = absRoot(root);
|
|
2298
|
+
const isTty = process.stdout && process.stdout.isTTY;
|
|
2299
|
+
const cy = s => isTty ? `\x1b[36m${s}\x1b[0m` : s;
|
|
2300
|
+
const gr = s => isTty ? `\x1b[32m${s}\x1b[0m` : s;
|
|
2301
|
+
const yl = s => isTty ? `\x1b[33m${s}\x1b[0m` : s;
|
|
2302
|
+
const dm = s => isTty ? `\x1b[2m${s}\x1b[0m` : s;
|
|
2303
|
+
function spawnChild(args, opts) {
|
|
2304
|
+
return cp.spawnSync(process.execPath, [__filename, ...args], Object.assign({ encoding: 'utf8', cwd: root, env: { ...process.env, LEERNESS_NO_BANNER: '1', LEERNESS_NO_PROMPT: '1' } }, opts || {}));
|
|
2305
|
+
}
|
|
2306
|
+
if (!sub || sub === 'help') {
|
|
2307
|
+
log(cy(`# leerness agent-mode (1.9.239) β μμ¨ λͺ¨λ μ μ© ν΅ν© λͺ
λ Ή`));
|
|
2308
|
+
log('');
|
|
2309
|
+
log(` start μ§μ
(handoff + drift --auto-fix + session-resume --auto-fix)`);
|
|
2310
|
+
log(` tick λ§€ λΌμ΄λ (pulse + ν΅μ¬ μ νΈ)`);
|
|
2311
|
+
log(` stop λ§κ° (session close --auto-apply-delivered --auto-cleanup-branches)`);
|
|
2312
|
+
log('');
|
|
2313
|
+
log(dm(` μ¬μ©μ λͺ
μ UR-0013 (Python + agent-mode ν¨μ¨ν)`));
|
|
2314
|
+
return;
|
|
2315
|
+
}
|
|
2316
|
+
if (sub === 'start') {
|
|
2317
|
+
log(cy(`# leerness agent-mode start (1.9.239)`));
|
|
2318
|
+
log(dm(` β 1. drift check --auto-fix (보μ + delivered + release cleanup)`));
|
|
2319
|
+
const r1 = spawnChild(['drift', 'check', root, '--auto-fix']);
|
|
2320
|
+
if (r1.status === 0) log(gr(` β drift auto-fix μλ£`)); else log(yl(` β drift auto-fix μ’
λ£ ${r1.status}`));
|
|
2321
|
+
log(dm(` β 2. session-resume --auto-fix (λΉμ μμ’
λ£ μλ ν볡)`));
|
|
2322
|
+
const r2 = spawnChild(['session-resume', '--path', root, '--auto-fix']);
|
|
2323
|
+
if (r2.status === 0) log(gr(` β session-resume μλ£`)); else log(yl(` β session-resume μ’
λ£ ${r2.status}`));
|
|
2324
|
+
log(dm(` β 3. handoff (컨ν
μ€νΈ μ μ¬)`));
|
|
2325
|
+
const r3 = spawnChild(['handoff', root]);
|
|
2326
|
+
if (r3.status === 0) log(gr(` β handoff μΆλ ₯ μλ£ (μ μ°Έμ‘°)`)); else log(yl(` β handoff μ’
λ£ ${r3.status}`));
|
|
2327
|
+
log('');
|
|
2328
|
+
log(gr(`β agent-mode start μλ£ β μμ¨ λΌμ΄λ μ§ν μ€λΉ`));
|
|
2329
|
+
return;
|
|
2330
|
+
}
|
|
2331
|
+
if (sub === 'tick') {
|
|
2332
|
+
// κ°λ²Όμ μ°μ β pulse λ§ νΈμΆ
|
|
2333
|
+
log(cy(`# leerness agent-mode tick (1.9.239) β κ°λ²Όμ΄ μν νμΈ`));
|
|
2334
|
+
const r = spawnChild(['pulse', '--path', root]);
|
|
2335
|
+
process.stdout.write(r.stdout || '');
|
|
2336
|
+
return;
|
|
2337
|
+
}
|
|
2338
|
+
if (sub === 'stop') {
|
|
2339
|
+
log(cy(`# leerness agent-mode stop (1.9.239) β ν΅ν© λ§κ°`));
|
|
2340
|
+
log(dm(` β session close --auto-apply-delivered --auto-cleanup-branches`));
|
|
2341
|
+
const r = spawnChild(['session', 'close', root, '--auto-apply-delivered', '--auto-cleanup-branches']);
|
|
2342
|
+
process.stdout.write(r.stdout || '');
|
|
2343
|
+
return;
|
|
2344
|
+
}
|
|
2345
|
+
log(yl(`unknown subcommand: ${sub}`));
|
|
2346
|
+
log(dm(` β leerness agent-mode help`));
|
|
2347
|
+
}
|
|
2348
|
+
|
|
2199
2349
|
// 1.9.234: recentChanges β μ΅κ·Ό N λΌμ΄λμ ν΅μ¬ λ³κ²½ μμ½ (git tag commit subject)
|
|
2200
2350
|
// μλ΅: [{ version, date, subject }] (κ°μ₯ μ΅κ·ΌλΆν°)
|
|
2201
2351
|
function _computeRecentChanges(root, limit = 5) {
|
|
@@ -14558,7 +14708,9 @@ function mcpServeCmd(root) {
|
|
|
14558
14708
|
{ 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' } } } },
|
|
14559
14709
|
{ name: 'leerness_pulse', description: '1.9.231 β ν μ€ μ’
ν© μμ½ (10 ν΅μ¬ μ§ν). μλ΅: { version, roundCount, mcpTools, memorySurface, security, health, driftScore, nextMilestone, etaDays, abnormalShutdown }. μΈλΆ AIκ° "leerness μν ν λμ 보기"λ₯Ό κ°λ²Όμ΄ λ¨μΌ νΈμΆλ‘ νμ. handoff λ³΄λ€ 5λ°° λΉ λ¦ (drift/health κ³μ° skip). μΈμ: { path? }', inputSchema: { type: 'object', properties: { path: { type: 'string' } } } },
|
|
14560
14710
|
{ name: 'leerness_commands', description: '1.9.233 β μΉ΄ν
κ³ λ¦¬νλ μ 체 CLI λͺ
λ Ή λͺ©λ‘ (9 μΉ΄ν
κ³ λ¦¬). μλ΅: { version, totalCommands, categories: { status, task, memory, audit, workflow, release, skill, bridge, config } }. μΈλΆ AIκ° "leerness κ° μ 곡νλ λͺ
λ Ήμ΄ λκ° μλ"λ₯Ό μ§μ νμ. λ§€λ΄μΌ/λμλ§ λμ μμ±. μΈμ: { path? }', inputSchema: { type: 'object', properties: { path: { type: 'string' } } } },
|
|
14561
|
-
{ name: 'leerness_release_cleanup', description: '1.9.236 (1.9.235 μλ νμ) β local release/* branches μ 리. main μ mergeλ κ²λ§ ν보 (unmerged 보νΈ, νμ¬ branch 보νΈ). μλ΅: { apply, keep, total, merged, unmerged, deleteCount, toDelete[], recent[], unmergedSample[] }. μΈλΆ AIκ° "μ΄μ λμ release branches μ 리 κ°λ₯?"μ νμ. κΈ°λ³Έ dry-run, apply: true μμλ§ μ€ μμ . μΈμ: { path?, apply? (default false), keep? (default 5) }', inputSchema: { type: 'object', properties: { path: { type: 'string' }, apply: { type: 'boolean' }, keep: { type: 'number' } } } }
|
|
14711
|
+
{ name: 'leerness_release_cleanup', description: '1.9.236 (1.9.235 μλ νμ) β local release/* branches μ 리. main μ mergeλ κ²λ§ ν보 (unmerged 보νΈ, νμ¬ branch 보νΈ). μλ΅: { apply, keep, total, merged, unmerged, deleteCount, toDelete[], recent[], unmergedSample[] }. μΈλΆ AIκ° "μ΄μ λμ release branches μ 리 κ°λ₯?"μ νμ. κΈ°λ³Έ dry-run, apply: true μμλ§ μ€ μμ . μΈμ: { path?, apply? (default false), keep? (default 5) }', inputSchema: { type: 'object', properties: { path: { type: 'string' }, apply: { type: 'boolean' }, keep: { type: 'number' } } } },
|
|
14712
|
+
{ name: 'leerness_py_check', description: '1.9.239 (μ¬μ©μ λͺ
μ UR-0013) β Python νμΌ λΆμ. μμ‘΄μ± 0 regex fallback. .md μΈ .py λ leerness μΈμ§. μλ΅: { totalFiles, totalLOC, totalImports, totalFuncs, totalClasses, totalTodos, biggest: [{ file, loc, funcs, classes }] }. μΈλΆ AIκ° "μ΄ νλ‘μ νΈ Python νλ©΄μ΄ μΌλ§λ λλ"λ₯Ό νμ. μΈμ: { path? }', inputSchema: { type: 'object', properties: { path: { type: 'string' } } } },
|
|
14713
|
+
{ name: 'leerness_agent_mode', description: '1.9.239 (μ¬μ©μ λͺ
μ UR-0013) β μμ¨ λͺ¨λ μ μ© ν΅ν© λͺ
λ Ή. start: handoff + drift --auto-fix + session-resume --auto-fix (μ§μ
). tick: pulse ν μ€ (λ§€ λΌμ΄λ). stop: session close --auto-apply-delivered --auto-cleanup-branches (λ§κ°). μΈλΆ AI κ° μμ¨ λΌμ΄λ μ§μ
/λ§€ λΌμ΄λ/λ§κ°μ λ¨μΌ νΈμΆλ‘ μν. μΈμ: { path?, sub (required: "start"|"tick"|"stop"|"help") }', inputSchema: { type: 'object', properties: { path: { type: 'string' }, sub: { type: 'string', enum: ['start', 'tick', 'stop', 'help'] } }, required: ['sub'] } }
|
|
14562
14714
|
];
|
|
14563
14715
|
|
|
14564
14716
|
function send(obj) {
|
|
@@ -14735,6 +14887,14 @@ function mcpServeCmd(root) {
|
|
|
14735
14887
|
// 1.9.233: μΉ΄ν
κ³ λ¦¬νλ μ 체 CLI λͺ
λ Ή λͺ©λ‘
|
|
14736
14888
|
cliArgs = ['commands', '--json'];
|
|
14737
14889
|
break;
|
|
14890
|
+
case 'leerness_py_check':
|
|
14891
|
+
// 1.9.239 (UR-0013): Python νμΌ λΆμ
|
|
14892
|
+
cliArgs = ['py-check', '--path', targetPath, '--json'];
|
|
14893
|
+
break;
|
|
14894
|
+
case 'leerness_agent_mode':
|
|
14895
|
+
// 1.9.239 (UR-0013): μμ¨ λͺ¨λ ν΅ν© (start/tick/stop)
|
|
14896
|
+
cliArgs = ['agent-mode', String(args.sub || 'help'), '--path', targetPath];
|
|
14897
|
+
break;
|
|
14738
14898
|
case 'leerness_release_cleanup':
|
|
14739
14899
|
// 1.9.236 (1.9.235): local release/* branches μ 리
|
|
14740
14900
|
cliArgs = ['release', 'cleanup', '--json'];
|
|
@@ -18406,6 +18566,10 @@ async function main() {
|
|
|
18406
18566
|
if (cmd === 'pulse') return pulseCmd(arg('--path', process.cwd()));
|
|
18407
18567
|
// 1.9.233: leerness commands β μΉ΄ν
κ³ λ¦¬νλ μ 체 CLI λͺ
λ Ή λͺ©λ‘
|
|
18408
18568
|
if (cmd === 'commands') return commandsCmd(arg('--path', process.cwd()));
|
|
18569
|
+
// 1.9.239: leerness py-check β Python νμΌ λΆμ (μ¬μ©μ λͺ
μ UR-0013)
|
|
18570
|
+
if (cmd === 'py-check') return pyCheckCmd(arg('--path', process.cwd()));
|
|
18571
|
+
// 1.9.239: leerness agent-mode <start|tick|stop> β μμ¨ λͺ¨λ μ μ© ν΅ν© λͺ
λ Ή (μ¬μ©μ λͺ
μ UR-0013)
|
|
18572
|
+
if (cmd === 'agent-mode') return agentModeCmd(arg('--path', process.cwd()), args[1]);
|
|
18409
18573
|
// 1.9.208: leerness constraints <list|check|add> β νλ«νΌ/API μ μ½ μ¬μ μ²΄ν¬ (μ¬μ©μ λͺ
μ)
|
|
18410
18574
|
if (cmd === 'constraints') return constraintsCmd(arg('--path', process.cwd()), args[1], ...args.slice(2));
|
|
18411
18575
|
// 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.239",
|
|
4
4
|
"description": "Leerness: λΉνκ΄΄ λ§μ΄κ·Έλ μ΄μ
, μλ λ²μ κ°μ§Β·μ
λ°μ΄νΈ, κ³ν/μ§ν/νΈλμ€ν μλν, κ²μΌλ¦Β·μν¬λ¦ΏΒ·μΈμ½λ© μλ κ°λ, Claude Code μ¬λμ ν΅ν©μ κ°μΆ νκ΅μ΄ μ°μ AI κ°λ° νλ€μ€.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"leerness",
|