leerness 1.9.69 → 1.9.71
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 +60 -0
- package/README.md +4 -2
- package/bin/harness.js +139 -3
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,65 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.9.71 — 2026-05-20
|
|
4
|
+
|
|
5
|
+
**`.env` / `.env.example` 자동 동기화 (보안 정책: 키만, 실제 값 절대 노출 안 함)**.
|
|
6
|
+
|
|
7
|
+
### Added — `leerness env check` / `env sync` 명령
|
|
8
|
+
- `leerness env check [<path>]` — `.env`에 있는데 `.env.example`에 없는 키 / 반대도 자동 감지.
|
|
9
|
+
- `--json`: 구조화된 JSON 출력 (CI 친화).
|
|
10
|
+
- exit code: `.env.example` 누락 키 ≥1 시 1 (보안 가시화).
|
|
11
|
+
- `leerness env sync [<path>]` — 누락 키만 `.env.example` 끝에 append (값은 빈 문자열).
|
|
12
|
+
|
|
13
|
+
### Improved — `leerness audit` 통합
|
|
14
|
+
- 매 audit 시 `.env` ↔ `.env.example` 자동 비교, 누락 시 warning 추가.
|
|
15
|
+
- `audit --fix` 시 누락 키 자동 추가 (보안 정책: 실제 값 미노출).
|
|
16
|
+
- `--no-env-check`로 비활성화 가능.
|
|
17
|
+
|
|
18
|
+
### 보안 정책 (검증됨)
|
|
19
|
+
- `.env`의 실제 값은 **절대** `.env.example`로 옮기지 않음.
|
|
20
|
+
- 추가되는 줄: `KEY=` (빈 문자열).
|
|
21
|
+
- 사용자 글로벌 룰 (.env 보안) 준수.
|
|
22
|
+
|
|
23
|
+
### Verified
|
|
24
|
+
- stress-v17 — env check / sync / audit 통합 + 보안 정책 + 누적 회귀.
|
|
25
|
+
- e2e 회귀: 219/219 PASS 유지.
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## 1.9.70 — 2026-05-19
|
|
30
|
+
|
|
31
|
+
**MCP server `tools/call` 자동 사용 통계** (1.9.65 usage-stats 확장).
|
|
32
|
+
|
|
33
|
+
### Added — MCP 도구별 호출 카운트
|
|
34
|
+
- MCP server가 `tools/call` 요청을 받을 때마다 도구 이름별 카운트를 `.harness/cache/usage-stats.json`의 `mcp.tools` 섹션에 기록.
|
|
35
|
+
- 별도 mtime 캐시 invalidation (1.9.65 _USAGE_CACHE 재활용).
|
|
36
|
+
- `leerness usage stats` 출력에 MCP 섹션 자동 노출:
|
|
37
|
+
```
|
|
38
|
+
## 🔌 MCP tools/call 통계 (1.9.70) — last: <ISO>
|
|
39
|
+
| MCP 도구 | 호출 수 |
|
|
40
|
+
| leerness_handoff | 8 |
|
|
41
|
+
| ... |
|
|
42
|
+
💡 드물게 호출된 도구 (≤N): leerness_xxx, ...
|
|
43
|
+
```
|
|
44
|
+
- 드물게 호출되는 도구 (전체 5% 미만)를 자동 식별 — AI 에이전트가 안 쓰는 도구가 있다는 가시화.
|
|
45
|
+
|
|
46
|
+
### Internal
|
|
47
|
+
- 새 헬퍼: `_bumpMcpUsage(root, toolName)` — atomic write + 캐시 invalidation.
|
|
48
|
+
- usage-stats.json 스키마 확장:
|
|
49
|
+
```json
|
|
50
|
+
{
|
|
51
|
+
"commands": {...},
|
|
52
|
+
"drift": {...},
|
|
53
|
+
"mcp": { "tools": {...}, "lastTool": "...", "lastAt": "..." }
|
|
54
|
+
}
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### Verified
|
|
58
|
+
- stress-v16 — MCP 카운트 정합성 + 13 도구 종합 호출 + 1.9.43~69 누적 회귀 + 성능.
|
|
59
|
+
- e2e 회귀: 219/219 PASS 유지.
|
|
60
|
+
|
|
61
|
+
---
|
|
62
|
+
|
|
3
63
|
## 1.9.69 — 2026-05-19
|
|
4
64
|
|
|
5
65
|
**handoff에 skill-suggestions.md rolling history hit 노출 (1.9.67 + 1.9.68 결합)**.
|
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,7 +12,7 @@
|
|
|
12
12
|
║ ██║ ██╔══╝ ██╔══╝ ██╔══██╗██║╚██╗██║██╔══╝ ╚════██║ ║
|
|
13
13
|
║ ███████╗███████╗███████╗██║ ██║██║ ╚████║███████╗███████║ ║
|
|
14
14
|
║ ╚══════╝╚══════╝╚══════╝╚═╝ ╚═╝╚═╝ ╚═══╝╚══════╝╚══════╝ ║
|
|
15
|
-
║ v1.9.
|
|
15
|
+
║ v1.9.71 AI Agent Reliability Harness ║
|
|
16
16
|
║ verify · remember · orchestrate · audit · prevent drift ║
|
|
17
17
|
╚══════════════════════════════════════════════════════════════╝
|
|
18
18
|
```
|
|
@@ -433,6 +433,8 @@ npm test # = node ./scripts/e2e.js
|
|
|
433
433
|
|
|
434
434
|
## 변경 이력 (최근)
|
|
435
435
|
|
|
436
|
+
- **1.9.71** — **`.env` / `.env.example` 자동 동기화** — `leerness env check` / `env sync` 명령 + `audit` 통합 (`--fix`로 누락 키 자동 추가). 보안 정책: 실제 값 절대 노출 안 함 (키만 추가, 값은 빈 문자열).
|
|
437
|
+
- **1.9.70** — **MCP server `tools/call` 자동 사용 통계** — 도구별 호출 카운트 (`.harness/cache/usage-stats.json#mcp.tools`) + `leerness usage stats` 출력에 MCP 섹션 + 드물게 호출되는 도구 식별.
|
|
436
438
|
- **1.9.69** — **handoff에 skill-suggestions.md history hit 노출** (fuzzy 매칭, 최근 2건 + top 2 매치). AI가 이전 세션 결정을 일관 유지. mtime 기반 캐시 (1.9.65/66/67 캐시 패밀리 연속).
|
|
437
439
|
- **1.9.68** — **`skill match` 결과 → `.harness/skill-suggestions.md` rolling history 자동 누적** (AI가 다음 세션에 이전 추천 참조 가능). `--no-save` / `LEERNESS_NO_SKILL_HISTORY=1`로 끄기.
|
|
438
440
|
- **1.9.67** — **handoff 자동 skill 추천 default ON** (jaccard 매칭) + lessons 인덱스에 task-log.md 실패 라인 통합 (회수 범위 확장).
|
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.
|
|
9
|
+
const VERSION = '1.9.71';
|
|
10
10
|
const MARK = '<!-- leerness:managed -->';
|
|
11
11
|
const README_START = '<!-- leerness:project-readme:start -->';
|
|
12
12
|
const README_END = '<!-- leerness:project-readme:end -->';
|
|
@@ -1480,6 +1480,32 @@ function audit(root) {
|
|
|
1480
1480
|
}
|
|
1481
1481
|
} catch {}
|
|
1482
1482
|
}
|
|
1483
|
+
// 1.9.71: .env / .env.example 동기화 감사 (--no-env-check로 끄기)
|
|
1484
|
+
if (!has('--no-env-check')) {
|
|
1485
|
+
try {
|
|
1486
|
+
const d = envDiff(root);
|
|
1487
|
+
if (exists(d.envPath) && exists(d.examplePath)) {
|
|
1488
|
+
if (d.inEnvOnly.length) {
|
|
1489
|
+
warnings++;
|
|
1490
|
+
warn(`.env에 있는 키 ${d.inEnvOnly.length}건이 .env.example에 누락: ${d.inEnvOnly.slice(0, 4).join(', ')}${d.inEnvOnly.length > 4 ? ' …' : ''}`);
|
|
1491
|
+
if (fix) {
|
|
1492
|
+
// 자동 동기화: 누락 키만 .env.example 끝에 append (값 비움)
|
|
1493
|
+
let example = read(d.examplePath);
|
|
1494
|
+
if (!example.endsWith('\n')) example += '\n';
|
|
1495
|
+
example += `\n# 1.9.71 audit --fix: 누락 키 자동 추가 (값은 빈 문자열, 보안 정책)\n`;
|
|
1496
|
+
for (const k of d.inEnvOnly) example += `${k}=\n`;
|
|
1497
|
+
writeUtf8(d.examplePath, example);
|
|
1498
|
+
ok(` ↳ fixed: .env.example에 ${d.inEnvOnly.length}건 자동 추가 (값은 빈 문자열, 1.9.71)`);
|
|
1499
|
+
fixed++;
|
|
1500
|
+
} else {
|
|
1501
|
+
log(` → 자동 동기화: leerness env sync 또는 leerness audit --fix`);
|
|
1502
|
+
}
|
|
1503
|
+
} else {
|
|
1504
|
+
ok('.env ↔ .env.example 동기화됨 (1.9.71)');
|
|
1505
|
+
}
|
|
1506
|
+
}
|
|
1507
|
+
} catch {}
|
|
1508
|
+
}
|
|
1483
1509
|
// 1.9.63: --strict — warnings ≥ threshold 시 failures로 승격 (CI 친화)
|
|
1484
1510
|
if (has('--strict')) {
|
|
1485
1511
|
const threshold = parseInt(arg('--threshold', '1'), 10);
|
|
@@ -3216,15 +3242,16 @@ function _banner(opts = {}) {
|
|
|
3216
3242
|
lines.push('');
|
|
3217
3243
|
for (const ln of lines) log(ln);
|
|
3218
3244
|
if (opts.quickStart) {
|
|
3219
|
-
log(C.bold(C.cyan(' ✨ 빠른 시작 (1.9.
|
|
3245
|
+
log(C.bold(C.cyan(' ✨ 빠른 시작 (1.9.71+ 워크플로)')));
|
|
3220
3246
|
log(' ' + C.green('npx leerness@latest init .') + C.dim(' # 신규 프로젝트 + 외부 AI CLI 설정'));
|
|
3221
3247
|
log(' ' + C.green('npx leerness handoff .') + C.dim(' # 컨텍스트 + lessons + 매칭 skill + 이전 history hit (1.9.69)'));
|
|
3222
3248
|
log(' ' + C.green('npx leerness skill match "<query>"') + C.dim(' # 매칭 skill + rolling history 자동 누적 (1.9.68)'));
|
|
3223
3249
|
log(' ' + C.green('npx leerness verify-claim T-0001 --run-tests') + C.dim(' # AI 거짓 완료 자동 검증'));
|
|
3250
|
+
log(' ' + C.green('npx leerness env check .') + C.dim(' # .env ↔ .env.example 동기화 검사 (1.9.71)'));
|
|
3224
3251
|
log(' ' + C.green('npx leerness session close .') + C.dim(' # 마감 + 다음 라운드 추천 (default)'));
|
|
3225
3252
|
log('');
|
|
3226
3253
|
log(C.bold(C.cyan(' 🤖 메인 에이전트 (Claude/Cursor/Copilot)용')));
|
|
3227
|
-
log(' ' + C.green('npx leerness mcp serve') + C.dim(' # MCP 서버 — 13 도구
|
|
3254
|
+
log(' ' + C.green('npx leerness mcp serve') + C.dim(' # MCP 서버 — 13 도구 + tools/call 자동 통계 (1.9.70)'));
|
|
3228
3255
|
log(' ' + C.green('npx leerness agents bench "<task>"') + C.dim(' # 3 CLI 동시 비교'));
|
|
3229
3256
|
log('');
|
|
3230
3257
|
}
|
|
@@ -6319,6 +6346,23 @@ function _bumpUsage(root, cmdName) {
|
|
|
6319
6346
|
} catch {}
|
|
6320
6347
|
}
|
|
6321
6348
|
|
|
6349
|
+
// 1.9.70: MCP tools/call 자동 사용 통계 — 도구별 호출 카운트
|
|
6350
|
+
function _bumpMcpUsage(root, toolName) {
|
|
6351
|
+
try {
|
|
6352
|
+
const stats = _readUsageStats(root);
|
|
6353
|
+
if (!stats.mcp) stats.mcp = { tools: {} };
|
|
6354
|
+
if (!stats.mcp.tools) stats.mcp.tools = {};
|
|
6355
|
+
stats.mcp.tools[toolName] = (stats.mcp.tools[toolName] || 0) + 1;
|
|
6356
|
+
stats.mcp.lastTool = toolName;
|
|
6357
|
+
stats.mcp.lastAt = new Date().toISOString();
|
|
6358
|
+
if (!stats.since) stats.since = today();
|
|
6359
|
+
const p = _usageStatsPath(root);
|
|
6360
|
+
mkdirp(path.dirname(p));
|
|
6361
|
+
writeUtf8(p, JSON.stringify(stats, null, 2) + '\n');
|
|
6362
|
+
try { _USAGE_CACHE.set(p, { stats, mtime: fs.statSync(p).mtimeMs }); } catch {}
|
|
6363
|
+
} catch {}
|
|
6364
|
+
}
|
|
6365
|
+
|
|
6322
6366
|
// 1.9.41: CHANGELOG.md를 파싱하여 from → to 사이 버전 차분 추출
|
|
6323
6367
|
// 반환: [{ version, date, body, newCommands, newFlags, newFiles }]
|
|
6324
6368
|
function _parseChangelogBetween(changelogText, fromV, toV) {
|
|
@@ -6993,6 +7037,8 @@ function mcpServeCmd(root) {
|
|
|
6993
7037
|
} else if (req.method === 'tools/call') {
|
|
6994
7038
|
const { name, arguments: args = {} } = req.params || {};
|
|
6995
7039
|
const targetPath = args.path || root;
|
|
7040
|
+
// 1.9.70: MCP tools/call 자동 사용 통계 — 어떤 도구가 자주/드물게 호출되는지 가시화
|
|
7041
|
+
try { _bumpMcpUsage(targetPath, name); } catch {}
|
|
6996
7042
|
let cliArgs;
|
|
6997
7043
|
try {
|
|
6998
7044
|
switch (name) {
|
|
@@ -7119,6 +7165,77 @@ function whatsNewCmd(root) {
|
|
|
7119
7165
|
log(` 4. 상세: \`cat CHANGELOG.md\` 또는 \`leerness whats-new --json\``);
|
|
7120
7166
|
}
|
|
7121
7167
|
|
|
7168
|
+
// 1.9.71: .env / .env.example 자동 동기화 — 누락 키 감지 + (옵션) 자동 추가
|
|
7169
|
+
// 보안 정책: .env의 실제 값은 절대 옮기지 않음. .env.example엔 키만 (빈 값).
|
|
7170
|
+
function _parseEnvKeys(text) {
|
|
7171
|
+
// KEY=value 형식, comment(#) 무시, 빈 줄 무시
|
|
7172
|
+
const out = new Set();
|
|
7173
|
+
for (const raw of String(text || '').split('\n')) {
|
|
7174
|
+
const line = raw.trim();
|
|
7175
|
+
if (!line || line.startsWith('#')) continue;
|
|
7176
|
+
const m = line.match(/^([A-Z_][A-Z0-9_]*)\s*=/i);
|
|
7177
|
+
if (m) out.add(m[1]);
|
|
7178
|
+
}
|
|
7179
|
+
return out;
|
|
7180
|
+
}
|
|
7181
|
+
function envDiff(root) {
|
|
7182
|
+
root = absRoot(root || process.cwd());
|
|
7183
|
+
const envPath = path.join(root, '.env');
|
|
7184
|
+
const examplePath = path.join(root, '.env.example');
|
|
7185
|
+
const envKeys = exists(envPath) ? _parseEnvKeys(read(envPath)) : new Set();
|
|
7186
|
+
const exKeys = exists(examplePath) ? _parseEnvKeys(read(examplePath)) : new Set();
|
|
7187
|
+
const inEnvOnly = [...envKeys].filter(k => !exKeys.has(k));
|
|
7188
|
+
const inExampleOnly = [...exKeys].filter(k => !envKeys.has(k));
|
|
7189
|
+
return { envPath, examplePath, envKeys: [...envKeys], exKeys: [...exKeys], inEnvOnly, inExampleOnly };
|
|
7190
|
+
}
|
|
7191
|
+
function envCheckCmd(root) {
|
|
7192
|
+
const d = envDiff(root);
|
|
7193
|
+
const isJson = has('--json');
|
|
7194
|
+
if (isJson) { log(JSON.stringify(d, null, 2)); return; }
|
|
7195
|
+
log(`# leerness env check (1.9.71)`);
|
|
7196
|
+
log(`.env 존재: ${exists(d.envPath)} · .env.example 존재: ${exists(d.examplePath)}`);
|
|
7197
|
+
log(`총 .env 키 ${d.envKeys.length} · .env.example 키 ${d.exKeys.length}`);
|
|
7198
|
+
if (d.inEnvOnly.length) {
|
|
7199
|
+
log('');
|
|
7200
|
+
log(`⚠ .env에 있는데 .env.example에 없는 키 ${d.inEnvOnly.length}건 (보안 정책: 값 없이 키만 추가):`);
|
|
7201
|
+
for (const k of d.inEnvOnly) log(` - ${k}`);
|
|
7202
|
+
}
|
|
7203
|
+
if (d.inExampleOnly.length) {
|
|
7204
|
+
log('');
|
|
7205
|
+
log(`ℹ .env.example에 있는데 .env에 없는 키 ${d.inExampleOnly.length}건 (런타임 누락 가능):`);
|
|
7206
|
+
for (const k of d.inExampleOnly) log(` - ${k}`);
|
|
7207
|
+
}
|
|
7208
|
+
if (!d.inEnvOnly.length && !d.inExampleOnly.length) {
|
|
7209
|
+
log('');
|
|
7210
|
+
ok('.env ↔ .env.example 동기화됨');
|
|
7211
|
+
} else {
|
|
7212
|
+
log('');
|
|
7213
|
+
log(`💡 자동 동기화: leerness env sync${d.inEnvOnly.length ? ' (.env.example에 누락 키 추가 — 값은 빈 문자열)' : ''}`);
|
|
7214
|
+
}
|
|
7215
|
+
// 1.9.71: exit code = .env.example 누락 키 있으면 1 (보안 가시화)
|
|
7216
|
+
if (d.inEnvOnly.length) process.exitCode = 1;
|
|
7217
|
+
}
|
|
7218
|
+
function envSyncCmd(root) {
|
|
7219
|
+
const d = envDiff(root);
|
|
7220
|
+
log(`# leerness env sync (1.9.71)`);
|
|
7221
|
+
if (!exists(d.examplePath)) {
|
|
7222
|
+
fail(`.env.example 없음 — leerness init . 먼저 실행`);
|
|
7223
|
+
return;
|
|
7224
|
+
}
|
|
7225
|
+
if (!d.inEnvOnly.length) {
|
|
7226
|
+
ok('동기화 불필요 — .env.example에 누락 키 없음');
|
|
7227
|
+
return;
|
|
7228
|
+
}
|
|
7229
|
+
// 누락 키를 .env.example 끝에 append (값 비움, 보안 정책 코멘트 동반)
|
|
7230
|
+
let example = read(d.examplePath);
|
|
7231
|
+
if (!example.endsWith('\n')) example += '\n';
|
|
7232
|
+
example += `\n# 1.9.71 sync: .env에서 발견된 누락 키 (값은 빈 문자열 — 보안 정책)\n`;
|
|
7233
|
+
for (const k of d.inEnvOnly) example += `${k}=\n`;
|
|
7234
|
+
writeUtf8(d.examplePath, example);
|
|
7235
|
+
ok(`${d.inEnvOnly.length}건 추가됨 → ${rel(root, d.examplePath)}`);
|
|
7236
|
+
for (const k of d.inEnvOnly) log(` + ${k}=`);
|
|
7237
|
+
}
|
|
7238
|
+
|
|
7122
7239
|
function usageStatsCmd(root) {
|
|
7123
7240
|
root = absRoot(root || process.cwd());
|
|
7124
7241
|
const stats = _readUsageStats(root);
|
|
@@ -7144,6 +7261,22 @@ function usageStatsCmd(root) {
|
|
|
7144
7261
|
log(`💡 drift 경고 ${stats.drift.skipped}회 스킵 → 1.9.38 학습: 임계 자동 완화 (--no-drift-check 빈도 ≥5)`);
|
|
7145
7262
|
}
|
|
7146
7263
|
}
|
|
7264
|
+
// 1.9.70: MCP tools/call 자동 사용 통계 — 어떤 도구가 자주/드물게 호출되는지
|
|
7265
|
+
if (stats.mcp && stats.mcp.tools && Object.keys(stats.mcp.tools).length) {
|
|
7266
|
+
const mcpEntries = Object.entries(stats.mcp.tools).sort((a, b) => b[1] - a[1]);
|
|
7267
|
+
const mcpTotal = mcpEntries.reduce((s, [, n]) => s + n, 0);
|
|
7268
|
+
log('');
|
|
7269
|
+
log(`## 🔌 MCP tools/call 통계 (1.9.70) — last: ${stats.mcp.lastAt || '(none)'}`);
|
|
7270
|
+
log(`| MCP 도구 | 호출 수 |`);
|
|
7271
|
+
log(`|---|---:|`);
|
|
7272
|
+
for (const [tool, n] of mcpEntries) log(`| ${tool} | ${n} |`);
|
|
7273
|
+
log('');
|
|
7274
|
+
log(`총 ${mcpTotal} 회 MCP 호출 · 도구 ${mcpEntries.length} 가지 사용`);
|
|
7275
|
+
// 드물게 호출되는 도구 식별 (전체의 5% 미만 호출)
|
|
7276
|
+
const threshold = Math.max(1, Math.floor(mcpTotal * 0.05));
|
|
7277
|
+
const rare = mcpEntries.filter(([, n]) => n <= threshold).map(([t]) => t);
|
|
7278
|
+
if (rare.length) log(`💡 드물게 호출된 도구 (≤${threshold}): ${rare.slice(0, 6).join(', ')}`);
|
|
7279
|
+
}
|
|
7147
7280
|
}
|
|
7148
7281
|
|
|
7149
7282
|
// 1.9.38: task sync — TodoWrite/외부 JSON에서 leerness task로 mirror
|
|
@@ -7431,6 +7564,9 @@ async function main() {
|
|
|
7431
7564
|
if (cmd === 'contract' && args[1] === 'verify') return contractVerifyCmd(args[2], args[3]);
|
|
7432
7565
|
if (cmd === 'drift' && (args[1] === 'check' || !args[1])) return driftCheckCmd(args[2] || arg('--path', process.cwd()));
|
|
7433
7566
|
if (cmd === 'usage' && (args[1] === 'stats' || !args[1])) return usageStatsCmd(args[2] || arg('--path', process.cwd()));
|
|
7567
|
+
// 1.9.71: leerness env check / sync — .env vs .env.example 자동 동기화
|
|
7568
|
+
if (cmd === 'env' && args[1] === 'check') return envCheckCmd(args[2] || arg('--path', process.cwd()));
|
|
7569
|
+
if (cmd === 'env' && args[1] === 'sync') return envSyncCmd(args[2] || arg('--path', process.cwd()));
|
|
7434
7570
|
if (cmd === 'whats-new') return whatsNewCmd(args[1] || arg('--path', process.cwd()));
|
|
7435
7571
|
if (cmd === 'reuse' && args[1] === 'autodetect') return reuseAutodetectCmd(args[2] || arg('--path', process.cwd()));
|
|
7436
7572
|
if (cmd === 'setup-agents' || cmd === 'setup' && args[1] === 'agents') return await setupAgentsCmd(args[1] && args[1] !== 'agents' ? args[1] : (args[2] || process.cwd()));
|