leerness 1.7.0 → 1.9.0

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.
@@ -0,0 +1,93 @@
1
+ # Publish Pre-check (leerness 1.9.0)
2
+
3
+ > ⚠ **Owner 권한 필수**: npm `leerness`의 메인테이너는 `gytlrgpfl <gytlrgpfl96@gmail.com>` 입니다. 이 계정으로 로그인되어 있거나 collaborator로 등록되어 있어야 publish가 통과합니다. 권한이 없으면 `E403 Forbidden`이 떨어집니다.
4
+
5
+ ## 1. 메타데이터 보강 (선택)
6
+
7
+ `package.json`의 다음 필드는 비어 있거나 일반적입니다. 사용자 정보로 채우는 것을 권장합니다.
8
+
9
+ ```json
10
+ {
11
+ "author": "leerness contributors",
12
+ "repository": { /* 비어있음 */ },
13
+ "bugs": { /* 비어있음 */ },
14
+ "homepage": ""
15
+ }
16
+ ```
17
+
18
+ 예:
19
+
20
+ ```json
21
+ "author": "Your Name <you@example.com>",
22
+ "repository": { "type": "git", "url": "git+https://github.com/<user>/leerness.git" },
23
+ "bugs": { "url": "https://github.com/<user>/leerness/issues" },
24
+ "homepage": "https://github.com/<user>/leerness#readme"
25
+ ```
26
+
27
+ publish 필수는 아니지만, npm 페이지 신뢰도와 사용자 경험을 위해 채워두면 좋습니다.
28
+
29
+ ## 2. 권한 확인
30
+
31
+ ```bash
32
+ npm whoami
33
+ # → 응답이 leerness의 owner인지 확인
34
+ npm owner ls leerness
35
+ # → 자신의 계정이 목록에 있는지 확인
36
+ ```
37
+
38
+ 권한이 없으면 collaborator 추가를 owner에게 요청해야 합니다.
39
+
40
+ ## 3. 로컬 검증
41
+
42
+ ```bash
43
+ node ./bin/harness.js --version # → 1.9.0
44
+ npm pack --dry-run # 패키지 내용 미리보기
45
+ node ./scripts/e2e.js # 30+개 시나리오 통과
46
+ ```
47
+
48
+ ## 4. 1.8.0 → 1.9.0 자동 업그레이드 시연 (선택)
49
+
50
+ ```bash
51
+ mkdir /tmp/lr-old; cd /tmp/lr-old
52
+ npx -y leerness@1.8.0 init . --language ko --skills recommended
53
+ LEERNESS_OFFLINE=1 npx -y -p /path/to/leerness-1.9.0.tgz leerness update . --yes
54
+ cat .harness/HARNESS_VERSION # → 1.9.0
55
+ ```
56
+
57
+ ## 5. publish dry-run
58
+
59
+ ```bash
60
+ npm publish --dry-run
61
+ # 또는
62
+ npm publish leerness-1.9.0.tgz --dry-run
63
+ ```
64
+
65
+ 확인:
66
+ - `package.json#files`와 실제 tarball 내용 일치
67
+ - 총 크기 (≈30~40 kB)
68
+ - bin → harness.js 매핑
69
+
70
+ ## 6. 실 publish
71
+
72
+ ```bash
73
+ npm login # 권한 있는 계정으로
74
+ npm publish --access public
75
+ ```
76
+
77
+ ## 7. publish 후 검증
78
+
79
+ ```bash
80
+ npm view leerness version # → 1.9.0
81
+ npx -y leerness@latest --version # → 1.9.0
82
+ mkdir test-install && cd test-install
83
+ npx -y leerness@latest init . --yes --language ko --skills recommended
84
+ npx -y leerness@latest verify .
85
+ ```
86
+
87
+ ## 8. 롤백
88
+
89
+ 24시간 이내라면 `npm unpublish leerness@1.9.0` 가능. 이후엔 1.9.1 패치 또는 deprecate.
90
+
91
+ ```bash
92
+ npm deprecate leerness@1.9.0 "Use 1.9.1+"
93
+ ```
package/package.json CHANGED
@@ -1,49 +1,52 @@
1
1
  {
2
2
  "name": "leerness",
3
- "version": "1.7.0",
4
- "description": "Leerness: AI 에이전트의 장기 맥락, 계획, 작업 추적, 스킬 라이브러리, 디자인/기능 일관성, 세션 인수인계를 관리하는 AX 최적화 개발 하네스.",
3
+ "version": "1.9.0",
4
+ "description": "Leerness: 비파괴 마이그레이션, 자동 버전 감지·업데이트, 계획/진행/핸드오프 자동화, 게으름·시크릿·인코딩 자동 가드, Claude Code 슬래시 통합을 갖춘 한국어 우선 AI 개발 하네스.",
5
5
  "keywords": [
6
6
  "leerness",
7
7
  "ai",
8
8
  "agent",
9
9
  "harness",
10
10
  "context-engineering",
11
+ "claude",
12
+ "claude-code",
13
+ "cursor",
14
+ "copilot",
11
15
  "skill-library",
12
16
  "project-memory",
13
17
  "task-tracking",
14
18
  "planning",
19
+ "handoff",
20
+ "anti-laziness",
21
+ "encoding",
22
+ "secret-scan",
23
+ "auto-update",
15
24
  "design-system",
16
- "developer-tools"
25
+ "developer-tools",
26
+ "korean"
17
27
  ],
28
+ "license": "MIT",
29
+ "author": "leerness contributors",
30
+ "type": "commonjs",
31
+ "engines": {
32
+ "node": ">=18"
33
+ },
18
34
  "bin": {
19
- "leerness": "./bin/harness.js"
35
+ "leerness": "bin/harness.js"
20
36
  },
21
37
  "files": [
22
- "bin/",
23
- "skill-packs/",
24
- "docs/",
25
- "harness.js",
38
+ "bin",
39
+ "scripts",
40
+ "docs",
26
41
  "README.md",
42
+ "CHANGELOG.md",
27
43
  "LICENSE"
28
44
  ],
29
45
  "scripts": {
30
- "test": "node ./bin/harness.js --help && node ./bin/harness.js init --yes --language ko --skills office,commerce-api ./tmp-harness-test && node ./bin/harness.js status ./tmp-harness-test && node ./bin/harness.js plan add '테스트 계획' --path ./tmp-harness-test && node ./bin/harness.js readme sync ./tmp-harness-test && node ./bin/harness.js consistency check ./tmp-harness-test && node ./bin/harness.js debug ./tmp-harness-test && node ./bin/harness.js verify ./tmp-harness-test",
46
+ "test": "node ./bin/harness.js --version && node ./scripts/e2e.js",
47
+ "test:smoke": "node ./scripts/e2e.js",
31
48
  "prepack": "node ./bin/harness.js --version"
32
49
  },
33
- "repository": {
34
- "type": "git",
35
- "url": "git+https://github.com/gugu9999gu/leerness.git"
36
- },
37
- "bugs": {
38
- "url": "https://github.com/gugu9999gu/leerness/issues"
39
- },
40
- "homepage": "https://github.com/gugu9999gu/leerness#readme",
41
- "author": "gugu9999gu",
42
- "license": "MIT",
43
- "type": "commonjs",
44
- "engines": {
45
- "node": ">=18"
46
- },
47
50
  "publishConfig": {
48
51
  "access": "public"
49
52
  }
package/scripts/e2e.js ADDED
@@ -0,0 +1,92 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+
4
+ const fs = require('fs');
5
+ const os = require('os');
6
+ const path = require('path');
7
+ const cp = require('child_process');
8
+
9
+ const CLI = path.resolve(__dirname, '..', 'bin', 'harness.js');
10
+ const tmp = fs.mkdtempSync(path.join(os.tmpdir(), 'leerness-e2e-'));
11
+ let failed = 0; let total = 0;
12
+
13
+ function run(label, args, opts = {}) {
14
+ total++;
15
+ const r = cp.spawnSync(process.execPath, [CLI, ...args], { cwd: opts.cwd || tmp, encoding: 'utf8' });
16
+ const ok = (r.status === 0) === !opts.expectFail;
17
+ process.stdout.write(`${ok ? '✓' : '✗'} ${label} (exit=${r.status})\n`);
18
+ if (!ok) { failed++; process.stdout.write(r.stdout || ''); process.stderr.write(r.stderr || ''); }
19
+ return { ok, stdout: r.stdout || '', stderr: r.stderr || '', status: r.status };
20
+ }
21
+
22
+ console.log(`# leerness e2e smoke @ ${tmp}`);
23
+
24
+ run('init', ['init', tmp, '--yes', '--language', 'ko', '--skills', 'recommended']);
25
+ run('status', ['status', tmp]);
26
+ run('verify', ['verify', tmp]);
27
+ run('debug', ['debug', tmp]);
28
+ run('check', ['check', tmp]);
29
+ run('audit', ['audit', tmp]);
30
+ run('scan secrets', ['scan', 'secrets', tmp]);
31
+ run('encoding check', ['encoding', 'check', tmp]);
32
+
33
+ const secretFile = path.join(tmp, 'fake-config.json');
34
+ fs.writeFileSync(secretFile, JSON.stringify({ openai: 'sk-' + 'A'.repeat(48) }));
35
+ run('scan secrets (detect)', ['scan', 'secrets', tmp], { expectFail: true });
36
+ fs.unlinkSync(secretFile);
37
+
38
+ run('plan add 1', ['plan', 'add', '마일스톤 A', '--status', 'planned', '--path', tmp]);
39
+ run('plan add 2', ['plan', 'add', '마일스톤 B', '--status', 'in-progress', '--path', tmp]);
40
+ run('task add', ['task', 'add', '사용자 요청 X', '--status', 'requested', '--path', tmp]);
41
+ run('task update T-0001', ['task', 'update', 'T-0001', '--status', 'in-progress', '--next', '검증 실행', '--path', tmp]);
42
+ run('task update T-0001 done', ['task', 'update', 'T-0001', '--status', 'done', '--evidence', 'review-evidence:e2e', '--path', tmp]);
43
+
44
+ const tracker = fs.readFileSync(path.join(tmp, '.harness/progress-tracker.md'), 'utf8');
45
+ const t1Count = (tracker.match(/^\| T-0001 \|/gm) || []).length;
46
+ total++;
47
+ if (t1Count === 1) console.log('✓ B1 in-place update: T-0001 row count = 1');
48
+ else { failed++; console.log(`✗ B1 in-place update FAILED: T-0001 row count = ${t1Count} (expected 1)`); }
49
+
50
+ fs.appendFileSync(path.join(tmp, '.harness/review-evidence.md'),
51
+ '\n## e2e\nTask: T-0001\nCommand: npm test\nExit: 0\nNote: e2e smoke\n');
52
+
53
+ run('session close', ['session', 'close', tmp]);
54
+ run('handoff', ['handoff', tmp]);
55
+ run('audit (post close)', ['audit', tmp]);
56
+ run('lazy detect', ['lazy', 'detect', tmp]);
57
+ run('memory search', ['memory', 'search', '마일스톤', '--path', tmp]);
58
+
59
+ const offline = Object.assign({}, process.env, { LEERNESS_OFFLINE: '1' });
60
+ total++;
61
+ {
62
+ const r = cp.spawnSync(process.execPath, [CLI, 'update', tmp, '--check'], { env: offline, encoding: 'utf8' });
63
+ const ok = r.status === 0 && /up to date|migration available/.test(r.stdout || '');
64
+ console.log(ok ? '✓ update --check (offline)' : `✗ update --check (offline) exit=${r.status}`);
65
+ if (!ok) { failed++; console.log(r.stdout || ''); console.error(r.stderr || ''); }
66
+ }
67
+
68
+ run('auto-update install', ['auto-update', 'install', tmp]);
69
+ total++;
70
+ {
71
+ const settingsFile = path.join(tmp, '.claude/settings.local.json');
72
+ if (fs.existsSync(settingsFile)) {
73
+ const s = JSON.parse(fs.readFileSync(settingsFile, 'utf8'));
74
+ const hasHook = (s.hooks?.SessionStart || []).some(h => h.command && h.command.includes('leerness update'));
75
+ if (hasHook) console.log('✓ SessionStart hook for update --check installed');
76
+ else { failed++; console.log('✗ SessionStart hook missing'); }
77
+ } else { failed++; console.log('✗ .claude/settings.local.json missing'); }
78
+ }
79
+
80
+ run('viewwork install', ['viewwork', 'install', tmp]);
81
+ run('viewwork emit', ['viewwork', 'emit', tmp, '--action', 'note', '--note', 'e2e ping']);
82
+ run('route planning', ['route', 'planning']);
83
+ run('route bugfix', ['route', 'bugfix']);
84
+ run('skill list', ['skill', 'list']);
85
+ run('skill info', ['skill', 'info', 'office']);
86
+ run('readme sync', ['readme', 'sync', tmp]);
87
+ run('consistency check', ['consistency', 'check', tmp]);
88
+ run('--version', ['--version']);
89
+ run('--help', ['--help']);
90
+
91
+ console.log(`\nE2E result: ${total - failed}/${total} passed`);
92
+ if (failed > 0) process.exit(1);
@@ -1,9 +0,0 @@
1
- # AX Consistency Guide
2
-
3
- 새 UI, API wrapper, validation, form, state handler를 만들기 전에 기존 요소를 확인합니다.
4
-
5
- 1. `design-system.md` 확인
6
- 2. `consistency-policy.md` 확인
7
- 3. `reuse-map.md` 확인
8
- 4. 동일 기능이 있으면 재사용 또는 확장
9
- 5. 새로 만들 수밖에 없으면 이유를 `reuse-map.md`에 기록
@@ -1,9 +0,0 @@
1
- # AX Migration Guide
2
-
3
- 마이그레이션은 비파괴가 원칙입니다.
4
-
5
- - 기존 문서는 먼저 `.harness/archive/`에 보존합니다.
6
- - `.env.example`과 `.gitignore`는 덮어쓰기보다 병합합니다.
7
- - `.harness/`와 관련 지침 파일은 삭제하지 않습니다.
8
- - 기존 designguide 계열 문서는 `.harness/design-system.md`로 병합합니다.
9
- - 마이그레이션 후 `leerness verify .`, `leerness debug .`, `leerness session close .`를 실행합니다.
@@ -1,9 +0,0 @@
1
- # AX Plan Guide
2
-
3
- AI 에이전트는 사용자 요청을 받으면 먼저 `plan.md`의 범위와 `progress-tracker.md`의 상태를 확인합니다.
4
-
5
- 1. 기존 계획의 일부인지 확인합니다.
6
- 2. 새 범위면 `plan.md`와 `progress-tracker.md`에 추가합니다.
7
- 3. 사용자가 제외한 작업은 삭제하지 않고 `dropped`로 기록합니다.
8
- 4. 완전히 신규 프로젝트라면 구현보다 계획표 작성이 우선입니다.
9
- 5. 작업 종료 시 `session close` 기준으로 완료/진행/미완료/예정/대기/보류/차단/드랍을 표시합니다.
package/harness.js DELETED
@@ -1,2 +0,0 @@
1
- #!/usr/bin/env node
2
- require('./bin/harness.js');
@@ -1,6 +0,0 @@
1
- # ads-analytics
2
-
3
- Leerness curated skill pack.
4
-
5
- - Sensitive data must be represented by environment variable names only.
6
- - Add verified implementation patterns here after AI review.
@@ -1,6 +0,0 @@
1
- # ai-verified-skill-publisher
2
-
3
- Leerness curated skill pack.
4
-
5
- - Sensitive data must be represented by environment variable names only.
6
- - Add verified implementation patterns here after AI review.
@@ -1,6 +0,0 @@
1
- # appstore-review
2
-
3
- Leerness curated skill pack.
4
-
5
- - Sensitive data must be represented by environment variable names only.
6
- - Add verified implementation patterns here after AI review.
@@ -1,6 +0,0 @@
1
- # commerce-api
2
-
3
- Leerness curated skill pack.
4
-
5
- - Sensitive data must be represented by environment variable names only.
6
- - Add verified implementation patterns here after AI review.
@@ -1,6 +0,0 @@
1
- # crawling
2
-
3
- Leerness curated skill pack.
4
-
5
- - Sensitive data must be represented by environment variable names only.
6
- - Add verified implementation patterns here after AI review.
@@ -1,6 +0,0 @@
1
- # firebase
2
-
3
- Leerness curated skill pack.
4
-
5
- - Sensitive data must be represented by environment variable names only.
6
- - Add verified implementation patterns here after AI review.
@@ -1,6 +0,0 @@
1
- # office
2
-
3
- Leerness curated skill pack.
4
-
5
- - Sensitive data must be represented by environment variable names only.
6
- - Add verified implementation patterns here after AI review.