leerness 1.9.399 β 1.9.400
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 +16 -0
- package/README.md +5 -5
- package/bin/harness.js +9 -6
- package/package.json +1 -1
- package/scripts/e2e.js +18 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.9.400 β 2026-06-07 π β anti-laziness λͺ
λ Ή --json μλ¬ κ΅¬μ‘°ν (7λ²μ§Έ λ²κ·ΈννΈ P1-B, UR-0105)
|
|
4
|
+
|
|
5
|
+
**π verify-claim / optimism-check / honesty-check μ `--json` μλ¬λ ꡬ쑰ν JSON β AI μμ΄μ νΈ self-gate κ²μ¦ λͺ
λ Ήμ μλν μ λ’°μ±.**
|
|
6
|
+
|
|
7
|
+
### λ°°κ²½ (7λ²μ§Έ λ²κ·ΈννΈ P1-B Β· failJson ν¨ν΄ νλ)
|
|
8
|
+
λ²κ·ΈννΈ: μ 3κ° anti-laziness κ²μ¦ λͺ
λ Ή(AI μμ΄μ νΈκ° μκΈ° κ²μ¦μ μ¬μ©)μ΄ μλ T-ID μ `--json` μΌλ‘ νΈμΆ μ `β ... μμ` ν
μ€νΈλ₯Ό stdout μ μΆλ ₯ β JSON.parse ν¬λμ. 1.9.398 μ failJson ν¬νΌλ₯Ό μ΄λ€μ νλ μ μ©.
|
|
9
|
+
|
|
10
|
+
### ꡬν
|
|
11
|
+
- verify-claim / optimism-check: missing_args / not_found λ₯Ό `failJson(_j, ...)` λ‘.
|
|
12
|
+
- honesty-check: T-ID not_found λ₯Ό failJson λ‘.
|
|
13
|
+
- μ¬λμ© μΆλ ₯(--json μμ λ) 무λ³κ²½.
|
|
14
|
+
|
|
15
|
+
### κ²μ¦ (νκ· 0)
|
|
16
|
+
- **selftest 145β146 PASS** (3κ° λͺ
λ Ή failJson μμ΄μ΄ μμ€ νμΈ).
|
|
17
|
+
- **E2E 338β339 PASS** (3κ° --json μλ¬ β {ok:false,code:not_found} exit1 + μ¬λμ© β ν
μ€νΈ 보쑴).
|
|
18
|
+
|
|
3
19
|
## 1.9.399 β 2026-06-07 β ν
μ΄λΈμ
injection μ°¨λ¨: task/rule νμ΄νΒ·κ°ν (7λ²μ§Έ λ²κ·ΈννΈ P1-A, UR-0104)
|
|
4
20
|
|
|
5
21
|
**π‘ λ°μ΄ν° λ¬΄κ²°μ± β task/rule ν
μ€νΈμ νμ΄ν(|)Β·κ°ν(\\n)μ΄ progress-tracker/rules.md νλ₯Ό μμΒ·κ°μ§ν μ£Όμ
Β·λ©±λ±μ± 무λ ₯ννλ κ²μ μ°¨λ¨(μ
μ΄μ€μΌμ΄ν).**
|
package/README.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
> **AI μ½λ© μμ΄μ νΈμ κ±°μ§ μλ£Β·μ€λ³΅Β·λ§κ°Β·μΆ©λμ λ§μμ£Όλ κ²μΒ·κΈ°μ΅Β·νμ
CLI νλ€μ€.**
|
|
4
4
|
> **A CLI harness that stops AI coding agents from faking completion, duplicating work, forgetting context, and colliding.**
|
|
5
5
|
|
|
6
|
-
[](https://www.npmjs.com/package/leerness) [](https://www.npmjs.com/package/leerness) []() []() []() []() []() []()
|
|
7
7
|
|
|
8
8
|
```
|
|
9
9
|
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
@@ -471,7 +471,7 @@ MIT β Β© leerness contributors
|
|
|
471
471
|
<!-- leerness:project-readme:start -->
|
|
472
472
|
## Leerness Project Harness
|
|
473
473
|
|
|
474
|
-
μ΄ νλ‘μ νΈλ Leerness v1.9.
|
|
474
|
+
μ΄ νλ‘μ νΈλ Leerness v1.9.400 νλ€μ€λ₯Ό μ¬μ©ν©λλ€. AI μμ΄μ νΈλ μμ
μ `leerness handoff`λ‘ μ»¨ν
μ€νΈλ₯Ό μ μ¬νκ³ , μμ
ν `leerness check`/`leerness audit`/`leerness session close`λ₯Ό μνν΄μΌ ν©λλ€.
|
|
475
475
|
|
|
476
476
|
### μ μ²΄μ± β AI μμ΄μ νΈ μ΄μ λ μ΄μ΄ (UR-0030)
|
|
477
477
|
|
|
@@ -525,7 +525,7 @@ leerness memory restore decision <date|title>
|
|
|
525
525
|
|
|
526
526
|
### MCP server (μΈλΆ AI ν΅ν©)
|
|
527
527
|
|
|
528
|
-
Leerness v1.9.
|
|
528
|
+
Leerness v1.9.400λ stdio JSON-RPC MCP serverλ₯Ό λ΄μ₯ν©λλ€ β Claude Code Β· Cursor Β· Codex CLI λ± μΈλΆ AIμ **85κ° λꡬ**λ₯Ό λ
ΈμΆ:
|
|
529
529
|
|
|
530
530
|
```jsonc
|
|
531
531
|
// μΉ΄ν
κ³ λ¦¬λ³
|
|
@@ -546,7 +546,7 @@ Leerness v1.9.399λ stdio JSON-RPC MCP serverλ₯Ό λ΄μ₯ν©λλ€ β Claude Cod
|
|
|
546
546
|
`<<autonomous-loop-dynamic>>` μ νΈλ§ 보λ΄λ©΄ AIκ°:
|
|
547
547
|
1) λ€μ λΌμ΄λ ν보 μ μ β 2) μ½λ λ³κ²½ β 3) stress-v* μ κ· μμ± + λμ νκ· β 4) e2e 219/219 β 5) npm pack + git tag + GitHub release β 6) main μλ push (1.9.140+) β 7) session close β 8) λ€μ λΌμ΄λ μμ½.
|
|
548
548
|
|
|
549
|
-
νμ¬ λμ : **70 λΌμ΄λ (1.9.40 β 1.9.
|
|
549
|
+
νμ¬ λμ : **70 λΌμ΄λ (1.9.40 β 1.9.400)** Β· λ§€ λΌμ΄λ GitHub release/νκ·Έ μμ± Β· _reports/λ λΉκ³΅κ° 보쑴.
|
|
550
550
|
|
|
551
551
|
### μ±λ₯ κ°μ΄λ (1.9.140 μΈ‘μ )
|
|
552
552
|
|
|
@@ -584,6 +584,6 @@ leerness release pack --close --auto-main-push
|
|
|
584
584
|
- `.harness/session-handoff.md`: λ€μ μΈμ
μΈμμΈκ³ (μλ μμ±)
|
|
585
585
|
- `.harness/lessons.md` / `decisions.md` / `rules.md`: μꡬ λ©λͺ¨λ¦¬ (5 surface)
|
|
586
586
|
|
|
587
|
-
Last synced by Leerness v1.9.
|
|
587
|
+
Last synced by Leerness v1.9.400: 2026-06-06
|
|
588
588
|
<!-- leerness:project-readme:end -->
|
|
589
589
|
|
package/bin/harness.js
CHANGED
|
@@ -31,7 +31,7 @@ const { _evidenceQuality, _parseEvidenceStats, _shellGuardAnalyze, _claimFileInG
|
|
|
31
31
|
// 1.9.295 (UR-0025 4λ¨κ³): μ μ λ°μ΄ν° μΉ΄νλ‘κ·Έ λͺ¨λ λΆλ¦¬ (λΉνκ΄΄, require-based).
|
|
32
32
|
const { CAPABILITY_SURFACE, POWERFUL_COMMANDS, ADAPTERS, REUSE_CATEGORIES, REUSE_CHECKLIST, _DEFAULT_PLATFORM_CONSTRAINTS, _DEFAULT_DOMAIN_CATALOG, _LSP_LANG_PATTERNS, OPTIMISM_PATTERNS, BUILT_IN_PERSONAS, STRINGS, BUILTIN_CATALOG, ROADMAP_STATUS_LABEL, ROADMAP_STATUS_COLOR, SECRET_PATTERNS, MERGE_OVERWRITE_FILES, MINIMAL_SKIP_KEYS, REQUIRED_WORKSPACE_FILES, KEYWORD_STOPWORDS, SKILL_CATALOG_PRESETS } = require('../lib/catalogs'); // 1.9.344/368/369 (UR-0025): catalog λΆλ¦¬ (MERGE_OVERWRITE_FILES/MINIMAL_SKIP_KEYS ν¬ν¨)
|
|
33
33
|
|
|
34
|
-
const VERSION = '1.9.
|
|
34
|
+
const VERSION = '1.9.400';
|
|
35
35
|
|
|
36
36
|
// 1.9.290 (UR-0037, Codex gpt-5.5 #4 μλ ΄): CLI μ μ© λΆμμ©μ require μ μ€ννμ§ μλλ€.
|
|
37
37
|
// μ΄μ : warning listener μ κ±° / NODE_OPTIONS λ³κ²½ / chcp IIFE κ° top-level μ¦μ μ€ν β require('harness') μ νΈμ€νΈ νλ‘μΈμ€ μ€μΌ.
|
|
@@ -3004,6 +3004,7 @@ function _selfTestCases() {
|
|
|
3004
3004
|
{ name: '6λ²μ§Έ μΈλΆνκ°/codex P1-A (UR-0098): install-safety λ μνΌ μ
Έ-λ¬΄κ΄ + hardeningNote (1.9.397)', run: () => { if (typeof installSafetyCmd !== 'function') return false; const save = process.argv; const _w = process.stdout.write; let out = ''; try { process.argv = ['node', 'h', 'install-safety', '--json']; process.stdout.write = s => { out += s; return true; }; installSafetyCmd({ json: true }); } catch {} finally { process.stdout.write = _w; process.argv = save; } let j; try { j = JSON.parse(out); } catch {} const noPosixPrefix = !!j && Array.isArray(j.safeInstall) && !j.safeInstall.some(x => /^npm_config_\w+=/.test(String(x).trim())); const crossShell = !!j && j.safeInstall.filter(x => String(x).includes('npx --yes')).length >= 2; const noteOk = !!j && typeof j.hardeningNote === 'string' && j.hardeningNote.includes('PowerShell'); return noPosixPrefix && crossShell && noteOk; } },
|
|
3005
3005
|
{ name: '6λ²μ§Έ μΈλΆνκ°/codex P1-C (UR-0099): --json μλ¬ κ²½λ‘ κ΅¬μ‘°ν failJson + μμ΄μ΄ (1.9.398)', run: () => { const io = require('../lib/io'); if (io.failJson !== failJson) return false; const _w = process.stdout.write; const saved = process.exitCode; let jOut = '', hOut = ''; let jExit = 0; try { process.stdout.write = s => { jOut += s; return true; }; process.exitCode = 0; failJson(true, 'tc', 'm'); jExit = process.exitCode; process.stdout.write = s => { hOut += s; return true; }; process.exitCode = 0; failJson(false, 'c', 'humanmsg'); } catch {} finally { process.stdout.write = _w; process.exitCode = saved; } let pj; try { pj = JSON.parse(jOut); } catch {} const jsonOk = !!pj && pj.ok === false && pj.code === 'tc' && pj.error === 'm' && jExit === 1; const humanOk = hOut.includes('β') && hOut.includes('humanmsg') && !hOut.includes('{'); const src = read(__filename); const wired = src.includes("failJson(_j, 'missing_args'") && src.includes("failJson(_j, 'spec_not_found'"); return jsonOk && humanOk && wired; } },
|
|
3006
3006
|
{ name: '7λ²μ§Έ λ²κ·ΈννΈ P1-A (UR-0104): ν
μ΄λΈμ
μμ ν _cellSafe/_cellUnescape (νμ΄ν/κ°ν injection μ°¨λ¨) (1.9.399)', run: () => { const m = require('../lib/pure-utils'); if (m._cellSafe !== _cellSafe || m._cellUnescape !== _cellUnescape) return false; const safe = _cellSafe('fix | bug\nrow2'); const noRaw = !/(?<!\\)\|/.test(safe) && !/[\r\n]/.test(safe); const pipeRt = _cellUnescape(_cellSafe('a | b | c')) === 'a | b | c'; const nlGone = _cellSafe('a\nb') === 'a b'; const src = read(__filename); const wired = src.includes('_cellSafe(r.request)') && src.includes('_cellSafe(r.rule)'); return noRaw && pipeRt && nlGone && wired; } },
|
|
3007
|
+
{ name: '7λ²μ§Έ λ²κ·ΈννΈ P1-B (UR-0105): verify-claim/optimism-check/honesty-check --json μλ¬ κ΅¬μ‘°ν (1.9.400)', run: () => { const src = read(__filename); const vc = /function verifyClaimCmd[\s\S]{0,400}?failJson\(_j, 'not_found'/.test(src); const oc = /function optimismCheckCmd[\s\S]{0,400}?failJson\(_j, 'not_found'/.test(src); const hc = /function honestyCheckCmd[\s\S]{0,900}?failJson\(has\('--json'\), 'not_found'/.test(src); return vc && oc && hc; } },
|
|
3007
3008
|
{ name: 'VERSION νμ (x.y.z)', run: () => /^\d+\.\d+\.\d+$/.test(VERSION) }
|
|
3008
3009
|
];
|
|
3009
3010
|
}
|
|
@@ -9235,10 +9236,11 @@ function _gitChangedFiles(root) {
|
|
|
9235
9236
|
// _claimFileInGit β lib/analyzers.js (1.9.304 UR-0025)
|
|
9236
9237
|
function verifyClaimCmd(root, taskId) {
|
|
9237
9238
|
root = absRoot(root);
|
|
9238
|
-
|
|
9239
|
+
const _j = has('--json'); // 1.9.400 (7λ²μ§Έ λ²κ·ΈννΈ P1-B, UR-0105): --json μλ¬λ ꡬ쑰ν
|
|
9240
|
+
if (!taskId) return failJson(_j, 'missing_args', 'verify-claim <T-ID> νμ. μ: leerness verify-claim T-0008');
|
|
9239
9241
|
const rows = readProgressRows(root);
|
|
9240
9242
|
const row = rows.find(r => r.id === taskId);
|
|
9241
|
-
if (!row) return
|
|
9243
|
+
if (!row) return failJson(_j, 'not_found', `progress-tracker.mdμ ${taskId} μμ.`);
|
|
9242
9244
|
|
|
9243
9245
|
const evidence = row.evidence || '';
|
|
9244
9246
|
// 1.9.20: νμΌ κ²½λ‘ μΆμΆ β λλ©μΈ ν΄λ μλ μΈμ + λ£¨νΈ λ©ννμΌ
|
|
@@ -9994,7 +9996,7 @@ function honestyCheckCmd(root, arg1) {
|
|
|
9994
9996
|
if (textArg) { subject = String(textArg); sourceLabel = '--text'; }
|
|
9995
9997
|
else if (arg1 && !arg1.startsWith('-')) {
|
|
9996
9998
|
const row = readProgressRows(root).find(r => r.id === arg1);
|
|
9997
|
-
if (!row) {
|
|
9999
|
+
if (!row) { failJson(has('--json'), 'not_found', `progress-tracker.mdμ ${arg1} μμ.`); return; } // 1.9.400 (UR-0105): --json μλ¬ κ΅¬μ‘°ν
|
|
9998
10000
|
subject = row.evidence || ''; sourceLabel = `${arg1} evidence`;
|
|
9999
10001
|
} else { fail('μ¬μ©λ²: leerness honesty-check <T-ID> λλ leerness honesty-check --text "<μ£Όμ₯>"'); process.exitCode = 1; return; }
|
|
10000
10002
|
const r = _epistemicHonestyCheck(subject);
|
|
@@ -10012,10 +10014,11 @@ function honestyCheckCmd(root, arg1) {
|
|
|
10012
10014
|
}
|
|
10013
10015
|
function optimismCheckCmd(root, taskId) {
|
|
10014
10016
|
root = absRoot(root || process.cwd());
|
|
10015
|
-
|
|
10017
|
+
const _j = has('--json'); // 1.9.400 (7λ²μ§Έ λ²κ·ΈννΈ P1-B, UR-0105): --json μλ¬λ ꡬ쑰ν
|
|
10018
|
+
if (!taskId) return failJson(_j, 'missing_args', 'optimism-check <T-ID> νμ. μ: leerness optimism-check T-0001');
|
|
10016
10019
|
const rows = readProgressRows(root);
|
|
10017
10020
|
const row = rows.find(r => r.id === taskId);
|
|
10018
|
-
if (!row) return
|
|
10021
|
+
if (!row) return failJson(_j, 'not_found', `progress-tracker.mdμ ${taskId} μμ.`);
|
|
10019
10022
|
|
|
10020
10023
|
const codeText = _scanCodeForPatterns(root);
|
|
10021
10024
|
const suspects = _detectOptimism(row.evidence || '', codeText);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "leerness",
|
|
3
|
-
"version": "1.9.
|
|
3
|
+
"version": "1.9.400",
|
|
4
4
|
"description": "Leerness: λΉνκ΄΄ λ§μ΄κ·Έλ μ΄μ
, μλ λ²μ κ°μ§Β·μ
λ°μ΄νΈ, κ³ν/μ§ν/νΈλμ€ν μλν, κ²μΌλ¦Β·μν¬λ¦ΏΒ·μΈμ½λ© μλ κ°λ, Claude Code μ¬λμ ν΅ν©μ κ°μΆ νκ΅μ΄ μ°μ AI κ°λ° νλ€μ€.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"leerness",
|
package/scripts/e2e.js
CHANGED
|
@@ -5584,5 +5584,23 @@ total++;
|
|
|
5584
5584
|
if (!ok) failed++;
|
|
5585
5585
|
}
|
|
5586
5586
|
|
|
5587
|
+
// 1.9.400 νκ· (7λ²μ§Έ λ²κ·ΈννΈ P1-B, UR-0105): verify-claim/optimism-check/honesty-check --json μλ¬κ° ꡬ쑰ν JSON + μ¬λμ© λ³΄μ‘΄
|
|
5588
|
+
total++;
|
|
5589
|
+
{
|
|
5590
|
+
let ok = false;
|
|
5591
|
+
try {
|
|
5592
|
+
const d = fs.mkdtempSync(path.join(os.tmpdir(), 'leerness-antilazyjson-'));
|
|
5593
|
+
cp.spawnSync(process.execPath, [CLI, 'init', d, '--yes', '--language', 'ko'], { encoding: 'utf8', timeout: 30000 });
|
|
5594
|
+
const jsonErr = (cmd) => { const r = cp.spawnSync(process.execPath, [CLI, cmd, 'T-9999', '--path', d, '--json'], { encoding: 'utf8', timeout: 15000 }); try { const j = JSON.parse(r.stdout); return j.ok === false && j.code === 'not_found' && r.status === 1; } catch { return false; } };
|
|
5595
|
+
const allJson = jsonErr('verify-claim') && jsonErr('optimism-check') && jsonErr('honesty-check');
|
|
5596
|
+
const hr = cp.spawnSync(process.execPath, [CLI, 'verify-claim', 'T-9999', '--path', d], { encoding: 'utf8', timeout: 15000 });
|
|
5597
|
+
const humanOk = hr.status === 1 && /β/.test(hr.stdout || '') && !/^\s*\{/.test(hr.stdout || '');
|
|
5598
|
+
fs.rmSync(d, { recursive: true, force: true });
|
|
5599
|
+
ok = allJson && humanOk;
|
|
5600
|
+
} catch {}
|
|
5601
|
+
console.log(ok ? 'β B(1.9.400) 7thλ²κ·ΈννΈ P1-B: anti-laziness(verify-claim/optimism/honesty) --json μλ¬ κ΅¬μ‘°ν + μ¬λμ© λ³΄μ‘΄ (UR-0105)' : 'β anti-laziness --json μλ¬ μ€ν¨');
|
|
5602
|
+
if (!ok) failed++;
|
|
5603
|
+
}
|
|
5604
|
+
|
|
5587
5605
|
console.log(`\nE2E result: ${total - failed}/${total} passed Β· ${((Date.now() - _e2eStart) / 1000).toFixed(0)}s`);
|
|
5588
5606
|
if (failed > 0) process.exit(1);
|