leerness 1.9.206 β 1.9.207
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 +45 -0
- package/README.md +3 -3
- package/bin/harness.js +217 -2
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,50 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.9.207 β 2026-05-22
|
|
4
|
+
|
|
5
|
+
**π₯ μ¬μ©μ μμ² λλ½ νμΈ μ μ°¨ MVP (μ¬μ©μ λͺ
μ).**
|
|
6
|
+
|
|
7
|
+
### μ¬μ©μ λͺ
μ
|
|
8
|
+
> *"leernessκ° μ μ©λ νλ‘μ νΈμμ, μ΅κ·Όμ λͺ
λ Ήλ°μ μ§νν κ²μ€μ λλ½λκ² μλμ§ νμΈνλ μ μ°¨λ μλμ§ νμΈν΄μ€ / λ€μ λΌμ΄λμ μ°Έμ‘°"*
|
|
9
|
+
|
|
10
|
+
### 1. `.harness/user-requests.json` β μ¬μ©μ μμ² λμ κΈ°λ‘
|
|
11
|
+
- `_userRequestsPath/_loadUserRequests/_writeUserRequests` νμΌ I/O ν¬νΌ
|
|
12
|
+
- `_recordUserRequest(root, text, opts)` β μλ ID λΆμ¬(UR-XXXX) + μ€λ³΅ λ°©μ§(λμΌ ν
μ€νΈ + open μν)
|
|
13
|
+
- `_updateUserRequest(root, id, patch)` β status μ ν (open β in-progress β completed/dropped)
|
|
14
|
+
- μ΅κ·Ό 200κ° μ μ§ (rotate)
|
|
15
|
+
|
|
16
|
+
### 2. `_auditUserRequests(root)` β λλ½ ν보 νμ§
|
|
17
|
+
- open/in-progress μμ² ν
μ€νΈμ 첫 12 λ¨μ΄ μΆμΆ β task-log/plan/decisions μ λΉκ΅
|
|
18
|
+
- hits β₯ min(3, wordsΓ0.5) β **tracked** (μ΄λκ° μμ
μ΄ μμλ¨)
|
|
19
|
+
- κ·Έ μΈ β **missing** (λλ½ ν보, AI/μ¬μ©μκ° μμ κ°λ₯μ±)
|
|
20
|
+
- 7μΌ+ open β **stale** (μ¬κ²ν νμ)
|
|
21
|
+
|
|
22
|
+
### 3. `leerness requests <sub>` CLI (μ¬μ©μ λͺ
μ β "νμΈ μ μ°¨")
|
|
23
|
+
- `audit` β missing/tracked/stale λ³΄κ³ (--json κ°λ₯)
|
|
24
|
+
- `add "<text>"` β μ¬μ©μ μμ² μλ κΈ°λ‘
|
|
25
|
+
- `list [--status open|completed|dropped]` β μ 체 μΆλ ₯
|
|
26
|
+
- `complete <UR-id>` / `drop <UR-id>` β μν μ ν
|
|
27
|
+
|
|
28
|
+
### 4. handoff ν€λλΌμΈ ν΅ν© (13λ²μ§Έ μμ)
|
|
29
|
+
- missing β₯ 1 μ: `π₯ λ―Έλ΅ μμ² N건` (red)
|
|
30
|
+
- open > 0 (λͺ¨λ tracked) μ: `π₯ μμ² N (tracked)` (green)
|
|
31
|
+
- ν€λλΌμΈ λΌλ²¨: `1.9.81/93/113/152/162/192/197/204/207`
|
|
32
|
+
|
|
33
|
+
### 5. λμ νκ· (1.9.200~206) β λͺ¨λ μ μ§
|
|
34
|
+
|
|
35
|
+
### 6. stress-v152 β 17/17 PASS
|
|
36
|
+
- 1.9.207 (8) + μ±λ₯ (2) + λμ νκ· (7)
|
|
37
|
+
- μ¬μ©μ μμ² λΌμ΄νμ¬μ΄ν΄ 격리 tmpdir ν
μ€νΈ (add β list β audit β complete β drop)
|
|
38
|
+
- μ€λ³΅ λ°©μ§ νμΈ
|
|
39
|
+
- μ±λ₯: --version cold start avg 2206ms Β· MCP 54 λꡬ 1597ms
|
|
40
|
+
|
|
41
|
+
### 7. μλ release (69 λΌμ΄λ main-push streak Β· 30 λΌμ΄λ npm publish streak)
|
|
42
|
+
- `release sync-main` μλ β main merge + npm publish leerness@1.9.207
|
|
43
|
+
- 1.9.140λΆν° main μλ push (69 λΌμ΄λ 무μ€λ¨)
|
|
44
|
+
- 1.9.178λΆν° npm publish (30 λΌμ΄λ 무μ€λ¨)
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
3
48
|
## 1.9.206 β 2026-05-22
|
|
4
49
|
|
|
5
50
|
**π i18n MVP + UI/UX ν¬νΌ (μ¬μ©μ λͺ
μ 2μ’
).**
|
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.207 AI Agent Reliability Harness + Sandbox β
|
|
16
16
|
β verify Β· remember Β· orchestrate Β· audit Β· sandbox Β· drift β
|
|
17
|
-
β
|
|
17
|
+
β π₯ μ¬μ©μ μμ² λλ½ νμΈ (requests audit) (μ¬μ©μ λͺ
μ) β
|
|
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.207';
|
|
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 μ²λ¦¬).
|
|
@@ -1918,6 +1918,94 @@ function _analyzeWakeupStatus(root) {
|
|
|
1918
1918
|
return { hasWakeup: true, latest, deltaMin, kind, pending: pending.length };
|
|
1919
1919
|
}
|
|
1920
1920
|
|
|
1921
|
+
// 1.9.207: μ¬μ©μ μμ² λλ½ νμΈ μ μ°¨ β μ¬μ©μ λͺ
μ
|
|
1922
|
+
// "μ΅κ·Όμ λͺ
λ Ήλ°μ μ§νν κ²μ€μ λλ½λκ² μλμ§ νμΈνλ μ μ°¨λ μλμ§"
|
|
1923
|
+
// .harness/user-requests.json μ μ¬μ©μ λͺ
μ μμ²μ λμ κΈ°λ‘ β audit μ task-log/plan/decisions μ λ§€μΉ β λλ½ λ³΄κ³
|
|
1924
|
+
// λ μ½λ ꡬ쑰: { id, text, recordedAt, status: 'open'|'in-progress'|'completed'|'dropped',
|
|
1925
|
+
// linkedTaskIds?, linkedPlanIds?, linkedDecisionIds?, notes?, completedAt?, droppedAt? }
|
|
1926
|
+
function _userRequestsPath(root) { return path.join(root, '.harness', 'user-requests.json'); }
|
|
1927
|
+
function _loadUserRequests(root) {
|
|
1928
|
+
try {
|
|
1929
|
+
const fp = _userRequestsPath(root);
|
|
1930
|
+
if (!exists(fp)) return { requests: [] };
|
|
1931
|
+
const j = JSON.parse(read(fp));
|
|
1932
|
+
return { requests: Array.isArray(j.requests) ? j.requests : [] };
|
|
1933
|
+
} catch { return { requests: [] }; }
|
|
1934
|
+
}
|
|
1935
|
+
function _writeUserRequests(root, requests) {
|
|
1936
|
+
try {
|
|
1937
|
+
mkdirp(path.join(root, '.harness'));
|
|
1938
|
+
writeUtf8(_userRequestsPath(root), JSON.stringify({ requests, updatedAt: new Date().toISOString() }, null, 2));
|
|
1939
|
+
return true;
|
|
1940
|
+
} catch { return false; }
|
|
1941
|
+
}
|
|
1942
|
+
function _recordUserRequest(root, text, opts = {}) {
|
|
1943
|
+
if (!text || typeof text !== 'string') return null;
|
|
1944
|
+
const state = _loadUserRequests(root);
|
|
1945
|
+
// μ€λ³΅ λ°©μ§: λμΌ ν
μ€νΈ + open μν μ΄λ―Έ μ‘΄μ¬ μ skip
|
|
1946
|
+
const norm = text.trim().slice(0, 500);
|
|
1947
|
+
const dup = state.requests.find(r => r.text === norm && (r.status === 'open' || r.status === 'in-progress'));
|
|
1948
|
+
if (dup) return dup;
|
|
1949
|
+
const id = 'UR-' + String(state.requests.length + 1).padStart(4, '0');
|
|
1950
|
+
const entry = {
|
|
1951
|
+
id, text: norm, recordedAt: new Date().toISOString(),
|
|
1952
|
+
status: opts.status || 'open',
|
|
1953
|
+
linkedTaskIds: opts.linkedTaskIds || [],
|
|
1954
|
+
linkedPlanIds: opts.linkedPlanIds || [],
|
|
1955
|
+
linkedDecisionIds: opts.linkedDecisionIds || [],
|
|
1956
|
+
notes: opts.notes || ''
|
|
1957
|
+
};
|
|
1958
|
+
state.requests.push(entry);
|
|
1959
|
+
// μ΅κ·Ό 200κ°λ§ μ μ§
|
|
1960
|
+
if (state.requests.length > 200) state.requests = state.requests.slice(-200);
|
|
1961
|
+
_writeUserRequests(root, state.requests);
|
|
1962
|
+
return entry;
|
|
1963
|
+
}
|
|
1964
|
+
function _updateUserRequest(root, id, patch) {
|
|
1965
|
+
const state = _loadUserRequests(root);
|
|
1966
|
+
const idx = state.requests.findIndex(r => r.id === id);
|
|
1967
|
+
if (idx < 0) return null;
|
|
1968
|
+
state.requests[idx] = { ...state.requests[idx], ...patch, updatedAt: new Date().toISOString() };
|
|
1969
|
+
if (patch.status === 'completed' && !state.requests[idx].completedAt) state.requests[idx].completedAt = new Date().toISOString();
|
|
1970
|
+
if (patch.status === 'dropped' && !state.requests[idx].droppedAt) state.requests[idx].droppedAt = new Date().toISOString();
|
|
1971
|
+
_writeUserRequests(root, state.requests);
|
|
1972
|
+
return state.requests[idx];
|
|
1973
|
+
}
|
|
1974
|
+
// audit: open/in-progress μμ² μ€ task-log μ λ§€μΉλλ μμ
μ΄ μλ νλͺ©μ "λλ½ ν보"λ‘ λ³΄κ³
|
|
1975
|
+
function _auditUserRequests(root) {
|
|
1976
|
+
const state = _loadUserRequests(root);
|
|
1977
|
+
const open = state.requests.filter(r => r.status === 'open' || r.status === 'in-progress');
|
|
1978
|
+
const taskLog = (() => { try { return read(path.join(root, '.harness', 'task-log.md')); } catch { return ''; } })();
|
|
1979
|
+
const plan = (() => { try { return read(path.join(root, '.harness', 'plan.md')); } catch { return ''; } })();
|
|
1980
|
+
const decisions = (() => { try { return read(path.join(root, '.harness', 'decisions.md')); } catch { return ''; } })();
|
|
1981
|
+
const haystack = (taskLog + '\n' + plan + '\n' + decisions).toLowerCase();
|
|
1982
|
+
const missing = [];
|
|
1983
|
+
const tracked = [];
|
|
1984
|
+
open.forEach(req => {
|
|
1985
|
+
const linked = (req.linkedTaskIds && req.linkedTaskIds.length > 0)
|
|
1986
|
+
|| (req.linkedPlanIds && req.linkedPlanIds.length > 0)
|
|
1987
|
+
|| (req.linkedDecisionIds && req.linkedDecisionIds.length > 0);
|
|
1988
|
+
// ν€μλ λ§€μΉ β μμ² ν
μ€νΈμ μ²μ 8λ¨μ΄ μ€ 3λ¨μ΄ μ΄μ task-log/plan/decisions μ μ‘΄μ¬ β tracked
|
|
1989
|
+
const words = req.text.toLowerCase().split(/[\s,.()/\\-]+/).filter(w => w.length >= 2).slice(0, 12);
|
|
1990
|
+
const hits = words.filter(w => haystack.includes(w)).length;
|
|
1991
|
+
const matched = hits >= Math.min(3, Math.ceil(words.length * 0.5));
|
|
1992
|
+
if (linked || matched) tracked.push({ ...req, hits, words: words.length });
|
|
1993
|
+
else missing.push({ ...req, hits, words: words.length });
|
|
1994
|
+
});
|
|
1995
|
+
// 7μΌ μ΄μ 묡μ open μμ² (stale)
|
|
1996
|
+
const now = Date.now();
|
|
1997
|
+
const stale = open.filter(r => (now - new Date(r.recordedAt).getTime()) > 7 * 24 * 60 * 60 * 1000);
|
|
1998
|
+
return {
|
|
1999
|
+
total: state.requests.length,
|
|
2000
|
+
open: open.length,
|
|
2001
|
+
missing,
|
|
2002
|
+
tracked,
|
|
2003
|
+
stale,
|
|
2004
|
+
completed: state.requests.filter(r => r.status === 'completed').length,
|
|
2005
|
+
dropped: state.requests.filter(r => r.status === 'dropped').length
|
|
2006
|
+
};
|
|
2007
|
+
}
|
|
2008
|
+
|
|
1921
2009
|
// 1.9.203: μλ λΌμ΄λ plan μ 리 β μ¬μ©μ λͺ
μ
|
|
1922
2010
|
// "λ°±κ·ΈλΌμ΄λμ λ€μ μμ
μ΄ μμκ°λ₯ν μμ μκ° + μΌμ΄λ¬μλ ν΄μΌνλ μΌμ μ 리"
|
|
1923
2011
|
// λΌμ΄λ λ§λ¬΄λ¦¬ μ .harness/auto-resume-plan.json μλ μ μ₯ β λ€μ wakeup μ μ¦μ μ€ν κ°λ₯
|
|
@@ -2027,6 +2115,122 @@ function resumeCmd(root) {
|
|
|
2027
2115
|
log(grn(`β resume μ€λΉ μλ£ β κΆμ₯: leerness handoff . λλ leerness next-action take`));
|
|
2028
2116
|
}
|
|
2029
2117
|
|
|
2118
|
+
// 1.9.207: leerness requests <sub> β μ¬μ©μ μμ² λλ½ νμΈ μ μ°¨ CLI (μ¬μ©μ λͺ
μ)
|
|
2119
|
+
// audit β open μμ² μ€ task-log/plan/decisions μ λ§€μΉ μ λλ νλͺ© λ³΄κ³ (λλ½ ν보)
|
|
2120
|
+
// add β μ¬μ©μ μμ² μλ κΈ°λ‘ (μ: leerness requests add "API rate limit 5/s μ μ©")
|
|
2121
|
+
// list β λͺ¨λ μμ² μΆλ ₯ (--json μ΅μ
)
|
|
2122
|
+
// complete <id> β μμ² μλ£ νμ
|
|
2123
|
+
// drop <id> β μμ² λλ‘ νμ (μ¬μ©μ λͺ
μ μ·¨μ)
|
|
2124
|
+
function requestsCmd(root, sub, ...rest) {
|
|
2125
|
+
root = absRoot(root);
|
|
2126
|
+
const isTty = process.stdout && process.stdout.isTTY;
|
|
2127
|
+
const cyan = s => isTty ? `\x1b[36m${s}\x1b[0m` : s;
|
|
2128
|
+
const grn = s => isTty ? `\x1b[32m${s}\x1b[0m` : s;
|
|
2129
|
+
const yel = s => isTty ? `\x1b[33m${s}\x1b[0m` : s;
|
|
2130
|
+
const red = s => isTty ? `\x1b[31m${s}\x1b[0m` : s;
|
|
2131
|
+
const dim = s => isTty ? `\x1b[2m${s}\x1b[0m` : s;
|
|
2132
|
+
|
|
2133
|
+
if (!sub || sub === 'help' || sub === '--help') {
|
|
2134
|
+
log(`# leerness requests (1.9.207) β μ¬μ©μ μμ² λλ½ νμΈ μ μ°¨`);
|
|
2135
|
+
log('');
|
|
2136
|
+
log(` audit β λλ½ ν보 + tracked + stale λ³΄κ³ (--json κ°λ₯)`);
|
|
2137
|
+
log(` add "<text>" β μ¬μ©μ μμ² μλ κΈ°λ‘`);
|
|
2138
|
+
log(` list β μ 체 μμ² μΆλ ₯ (--json κ°λ₯, --status open|completed|dropped)`);
|
|
2139
|
+
log(` complete <id> β μμ² μλ£ νμ (μ: UR-0003)`);
|
|
2140
|
+
log(` drop <id> β μμ² λλ‘ νμ`);
|
|
2141
|
+
return;
|
|
2142
|
+
}
|
|
2143
|
+
|
|
2144
|
+
if (sub === 'add') {
|
|
2145
|
+
const text = rest.filter(x => !x.startsWith('-')).join(' ');
|
|
2146
|
+
if (!text) { console.error('Usage: leerness requests add "<request text>"'); process.exit(1); }
|
|
2147
|
+
const entry = _recordUserRequest(root, text);
|
|
2148
|
+
if (!entry) { console.error('failed to record'); process.exit(1); }
|
|
2149
|
+
if (has('--json')) { log(JSON.stringify(entry, null, 2)); return; }
|
|
2150
|
+
log(grn(`β recorded ${entry.id}: ${entry.text}`));
|
|
2151
|
+
return;
|
|
2152
|
+
}
|
|
2153
|
+
|
|
2154
|
+
if (sub === 'list') {
|
|
2155
|
+
const state = _loadUserRequests(root);
|
|
2156
|
+
const filterStatus = arg('--status', null);
|
|
2157
|
+
let list = state.requests;
|
|
2158
|
+
if (filterStatus) list = list.filter(r => r.status === filterStatus);
|
|
2159
|
+
if (has('--json')) { log(JSON.stringify({ total: state.requests.length, filtered: list.length, requests: list }, null, 2)); return; }
|
|
2160
|
+
log(cyan(`# leerness requests list (1.9.207)`));
|
|
2161
|
+
log(` total ${state.requests.length}${filterStatus ? ` Β· filter status=${filterStatus} β ${list.length}` : ''}`);
|
|
2162
|
+
log('');
|
|
2163
|
+
if (list.length === 0) { log(dim(' (μμ)')); return; }
|
|
2164
|
+
for (const r of list) {
|
|
2165
|
+
const statusIcon = r.status === 'completed' ? 'β' : (r.status === 'dropped' ? 'β' : (r.status === 'in-progress' ? 'βΆ' : 'β―'));
|
|
2166
|
+
const recordedDay = (r.recordedAt || '').slice(0, 10);
|
|
2167
|
+
log(` ${statusIcon} [${r.id}] ${dim(recordedDay)} ${r.text.slice(0, 100)}${r.text.length > 100 ? 'β¦' : ''}`);
|
|
2168
|
+
if (r.linkedTaskIds && r.linkedTaskIds.length > 0) log(dim(` linked tasks: ${r.linkedTaskIds.join(', ')}`));
|
|
2169
|
+
}
|
|
2170
|
+
return;
|
|
2171
|
+
}
|
|
2172
|
+
|
|
2173
|
+
if (sub === 'complete') {
|
|
2174
|
+
const id = rest[0];
|
|
2175
|
+
if (!id) { console.error('Usage: leerness requests complete <id>'); process.exit(1); }
|
|
2176
|
+
const updated = _updateUserRequest(root, id, { status: 'completed' });
|
|
2177
|
+
if (!updated) { console.error(`request not found: ${id}`); process.exit(1); }
|
|
2178
|
+
if (has('--json')) { log(JSON.stringify(updated, null, 2)); return; }
|
|
2179
|
+
log(grn(`β completed ${updated.id}`));
|
|
2180
|
+
return;
|
|
2181
|
+
}
|
|
2182
|
+
|
|
2183
|
+
if (sub === 'drop') {
|
|
2184
|
+
const id = rest[0];
|
|
2185
|
+
if (!id) { console.error('Usage: leerness requests drop <id>'); process.exit(1); }
|
|
2186
|
+
const updated = _updateUserRequest(root, id, { status: 'dropped' });
|
|
2187
|
+
if (!updated) { console.error(`request not found: ${id}`); process.exit(1); }
|
|
2188
|
+
if (has('--json')) { log(JSON.stringify(updated, null, 2)); return; }
|
|
2189
|
+
log(yel(`β dropped ${updated.id}`));
|
|
2190
|
+
return;
|
|
2191
|
+
}
|
|
2192
|
+
|
|
2193
|
+
if (sub === 'audit') {
|
|
2194
|
+
const audit = _auditUserRequests(root);
|
|
2195
|
+
if (has('--json')) { log(JSON.stringify(audit, null, 2)); return; }
|
|
2196
|
+
log(cyan(`# leerness requests audit (1.9.207) β μ¬μ©μ μμ² λλ½ νμΈ μ μ°¨`));
|
|
2197
|
+
log('');
|
|
2198
|
+
log(` π ν΅κ³: total ${audit.total} Β· open ${audit.open} Β· completed ${audit.completed} Β· dropped ${audit.dropped}`);
|
|
2199
|
+
log('');
|
|
2200
|
+
if (audit.missing.length === 0) {
|
|
2201
|
+
log(grn(` β λλ½ μμ β open μμ² λͺ¨λ task-log/plan/decisions μ νμ μμ`));
|
|
2202
|
+
} else {
|
|
2203
|
+
log(red(` β λλ½ ν보 ${audit.missing.length}건 (open μνμ΄λ task/plan/decisions λ§€μΉ μμ):`));
|
|
2204
|
+
for (const m of audit.missing) {
|
|
2205
|
+
log(` β’ [${m.id}] ${m.text.slice(0, 90)}${m.text.length > 90 ? 'β¦' : ''}`);
|
|
2206
|
+
log(dim(` ${m.recordedAt.slice(0, 10)} Β· hits=${m.hits}/${m.words}`));
|
|
2207
|
+
}
|
|
2208
|
+
log('');
|
|
2209
|
+
log(dim(` β κΆμ₯: λλ½ νλͺ©λ³ leerness task add "<μμ²>" λλ leerness requests complete <id>`));
|
|
2210
|
+
}
|
|
2211
|
+
if (audit.tracked.length > 0) {
|
|
2212
|
+
log('');
|
|
2213
|
+
log(grn(` β tracked ${audit.tracked.length}건 (open + task/plan/decisions λ§€μΉλ¨):`));
|
|
2214
|
+
for (const t of audit.tracked.slice(0, 5)) {
|
|
2215
|
+
log(` β’ [${t.id}] ${t.text.slice(0, 80)}${t.text.length > 80 ? 'β¦' : ''} ${dim(`(hits=${t.hits})`)}`);
|
|
2216
|
+
}
|
|
2217
|
+
}
|
|
2218
|
+
if (audit.stale.length > 0) {
|
|
2219
|
+
log('');
|
|
2220
|
+
log(yel(` β³ stale ${audit.stale.length}건 (7μΌ+ open):`));
|
|
2221
|
+
for (const s of audit.stale.slice(0, 5)) {
|
|
2222
|
+
const days = Math.floor((Date.now() - new Date(s.recordedAt).getTime()) / 86400000);
|
|
2223
|
+
log(` β’ [${s.id}] ${days}μΌ ${s.text.slice(0, 70)}β¦`);
|
|
2224
|
+
}
|
|
2225
|
+
}
|
|
2226
|
+
return;
|
|
2227
|
+
}
|
|
2228
|
+
|
|
2229
|
+
console.error(`Unknown subcommand: ${sub}`);
|
|
2230
|
+
console.error(`Run: leerness requests help`);
|
|
2231
|
+
process.exit(1);
|
|
2232
|
+
}
|
|
2233
|
+
|
|
2030
2234
|
// 1.9.199: wakeup miss μλ ν볡 κ°ν β last-handoff timestamp κΈ°λ‘ + 25min κΈ°λ interval μ λ° μΈ‘μ
|
|
2031
2235
|
// μ¬μ©μ λͺ
μ (1.9.198 νμ): "22:01μ λΌμ΄λμ μλμ§μ
λμ§μμμ΄"
|
|
2032
2236
|
// 1.9.196 task-log mtime κΈ°λ° detector λ task-log κ° μμ£Ό μ μ
λ°μ΄νΈλλ©΄ false positive.
|
|
@@ -4061,10 +4265,19 @@ function handoff(root) {
|
|
|
4061
4265
|
parts.push(`π backend ${pb.ready}/${pb.total} (${ageLabel}${pb.expired ? 'β ' : 'β'})`);
|
|
4062
4266
|
}
|
|
4063
4267
|
} catch {}
|
|
4268
|
+
// 13) 1.9.207: μ¬μ©μ μμ² λλ½ νμΈ μ μ°¨ (μ¬μ©μ λͺ
μ) β λλ½ ν보 β₯ 1 μ ν€λλΌμΈ λ
ΈμΆ
|
|
4269
|
+
try {
|
|
4270
|
+
const audit = _auditUserRequests(root);
|
|
4271
|
+
if (audit.missing && audit.missing.length > 0) {
|
|
4272
|
+
parts.push(`π₯ λ―Έλ΅ μμ² ${audit.missing.length}건`);
|
|
4273
|
+
} else if (audit.open > 0) {
|
|
4274
|
+
parts.push(`π₯ μμ² ${audit.open} (tracked)`);
|
|
4275
|
+
}
|
|
4276
|
+
} catch {}
|
|
4064
4277
|
if (parts.length) {
|
|
4065
4278
|
const isTty = process.stdout && process.stdout.isTTY;
|
|
4066
4279
|
const cy = s => isTty ? `\x1b[36m${s}\x1b[0m` : s;
|
|
4067
|
-
log(cy(`π ν€λλΌμΈ (1.9.81/93/113/152/162/192/197/204): ${parts.join(' Β· ')}`));
|
|
4280
|
+
log(cy(`π ν€λλΌμΈ (1.9.81/93/113/152/162/192/197/204/207): ${parts.join(' Β· ')}`));
|
|
4068
4281
|
}
|
|
4069
4282
|
} catch {}
|
|
4070
4283
|
}
|
|
@@ -15353,6 +15566,8 @@ async function main() {
|
|
|
15353
15566
|
if (cmd === 'next-action') return nextActionCmd(arg('--path', process.cwd()), args[1], ...args.slice(2));
|
|
15354
15567
|
// 1.9.203: leerness resume β auto-resume-plan μ½κ³ λ€μ λΌμ΄λ μ¦μ μλ΄ (μ¬μ©μ λͺ
μ)
|
|
15355
15568
|
if (cmd === 'resume') return resumeCmd(arg('--path', process.cwd()));
|
|
15569
|
+
// 1.9.207: leerness requests <audit|add|list|complete|drop> β μ¬μ©μ μμ² λλ½ νμΈ μ μ°¨ (μ¬μ©μ λͺ
μ)
|
|
15570
|
+
if (cmd === 'requests') return requestsCmd(arg('--path', process.cwd()), args[1], ...args.slice(2));
|
|
15356
15571
|
if (cmd === 'rule' && args[1] === 'add') return ruleAdd(arg('--path', process.cwd()), args.slice(2).filter(x => !x.startsWith('-')).join(' '));
|
|
15357
15572
|
if (cmd === 'rule' && args[1] === 'list') return ruleList(arg('--path', process.cwd()));
|
|
15358
15573
|
if (cmd === 'rule' && args[1] === 'remove') return ruleRemove(arg('--path', process.cwd()), args[2]);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "leerness",
|
|
3
|
-
"version": "1.9.
|
|
3
|
+
"version": "1.9.207",
|
|
4
4
|
"description": "Leerness: λΉνκ΄΄ λ§μ΄κ·Έλ μ΄μ
, μλ λ²μ κ°μ§Β·μ
λ°μ΄νΈ, κ³ν/μ§ν/νΈλμ€ν μλν, κ²μΌλ¦Β·μν¬λ¦ΏΒ·μΈμ½λ© μλ κ°λ, Claude Code μ¬λμ ν΅ν©μ κ°μΆ νκ΅μ΄ μ°μ AI κ°λ° νλ€μ€.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"leerness",
|