leerness 1.2.0 → 1.3.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.
package/README.md CHANGED
@@ -1,21 +1,8 @@
1
1
  # Leerness
2
2
 
3
- **Leerness는 AI 에이전트가 대규모 프로젝트에서도 맥락, 규율, 디자인/기능 일관성, 검증된 스킬 라이브러리를 유지하도록 돕는 AX 최적화 개발 하네스입니다.**
3
+ **Leerness는 AI 에이전트가 대규모 프로젝트에서도 필요한 문서를 먼저 읽고, 작업 적재적소에 프로젝트 메모리를 갱신하도록 만드는 AX 최적화 개발 하네스입니다.**
4
4
 
5
- Leerness 단순한 프롬프트 모음이 아닙니다. 프로젝트 안에 장기 기억, 작업 규칙, 금지사항, 디자인 기준, 기능 계약, 검증된 스킬 데이터를 설치해서 AI 에이전트가 매번 처음부터 추측하지 않고 같은 기준으로 개발하도록 만듭니다.
6
-
7
- ## 왜 필요한가
8
-
9
- AI 코딩 에이전트는 빠르지만, 프로젝트가 커질수록 아래 문제가 생깁니다.
10
-
11
- - 이전 결정과 현재 방향을 잊는다.
12
- - 기존 구조와 다른 방식으로 새 코드를 만든다.
13
- - 성공했던 구현 패턴을 반복 활용하지 못한다.
14
- - 민감정보 처리 규칙을 일관되게 지키지 못한다.
15
- - UI, API, 상태, 오류 처리 방식이 화면마다 달라진다.
16
- - 다음 세션에서 어디까지 작업했는지 다시 설명해야 한다.
17
-
18
- Leerness는 이 문제를 `.harness/` 지식 저장소와 검증된 스킬 라이브러리로 해결합니다.
5
+ Leerness 목적은 단순히 `.md` 파일을 많이 만드는 것이 아닙니다. AI가 어떤 상황에 어떤 파일을 봐야 하는지, 어떤 작업 어떤 파일을 갱신해야 하는지까지 명확히 지시합니다.
19
6
 
20
7
  ## 핵심 개념
21
8
 
@@ -23,16 +10,16 @@ Leerness는 이 문제를 `.harness/` 지식 저장소와 검증된 스킬 라
23
10
  Agent = Model + Leerness Harness
24
11
  ```
25
12
 
26
- 모델은 추론하고, Leerness는 프로젝트의 기억과 작업 규율을 제공합니다.
13
+ 모델은 추론하고, Leerness는 다음을 제공합니다.
27
14
 
28
15
  | 영역 | 역할 |
29
16
  |---|---|
30
- | 프로젝트 메모리 | 목적, 현재 상태, 아키텍처, 결정 로그, 다음 작업 유지 |
31
- | Guardrails | 민감정보, 보안, 리팩토링, API/DB 변경 금지 규칙 정의 |
32
- | Design System | UI/UX, 컴포넌트, 간격, 상태 표현 기준 유지 |
33
- | Feature Contracts | 기능별 입력, 출력, 상태, 오류, 검증 기준 기록 |
34
- | Skill Libraries | 성공한 구현 방식을 재사용 가능한 스킬로 축적 |
35
- | AX Guide | AI가 읽고 실행하기 쉬운 업로드/업데이트/병합/마이그레이션 절차 제공 |
17
+ | Context Routing | 작업 유형별로 읽을 파일과 갱신할 파일을 지정 |
18
+ | Writeback Policy | 어떤 정보를 어느 `.harness/*.md` 파일에 기록할지 정의 |
19
+ | Task Type Map | 사용자 요청을 feature/ui/release/migration 등으로 분류 |
20
+ | Project Memory | 목적, 현재 상태, 아키텍처, 결정 로그, 릴리즈 조건 유지 |
21
+ | Skill Libraries | 검증된 성공 패턴을 재사용 가능한 스킬로 설치/배포 |
22
+ | AX Guides | AI가 구버전 마이그레이션 또는 신규 설치를 안전하게 수행하도록 안내 |
36
23
 
37
24
  ## 설치
38
25
 
@@ -40,219 +27,134 @@ Agent = Model + Leerness Harness
40
27
  npx leerness init
41
28
  ```
42
29
 
43
- 추천 스킬 포함 설치:
30
+ 추천 스킬 포함:
44
31
 
45
32
  ```bash
46
33
  npx leerness init --skills recommended
47
34
  ```
48
35
 
49
- 필요한 스킬만 선택 설치:
50
-
51
- ```bash
52
- npx leerness init --skills office,commerce-api,crawling,ai-verified-skill-publisher
53
- ```
54
-
55
- 특정 경로에 설치:
36
+ 기존 프로젝트 또는 구버전 하네스 마이그레이션:
56
37
 
57
38
  ```bash
58
- npx leerness init ./my-project
39
+ npx leerness migrate --dry-run
40
+ npx leerness migrate
59
41
  ```
60
42
 
61
43
  ## 주요 명령어
62
44
 
63
45
  ```bash
64
- leerness init [path] [--skills recommended|all|office,commerce-api]
46
+ leerness init [path] [--yes] [--skills recommended|all|office,commerce-api]
47
+ leerness migrate [path] [--dry-run]
65
48
  leerness status [path]
66
49
  leerness verify [path]
50
+ leerness route <task-type>
67
51
 
68
52
  leerness skill list
69
53
  leerness skill info <name>
70
54
  leerness skill add <name>
71
- leerness skill remove <name>
72
- leerness skill update <name>
73
55
  leerness skill learn <name> --from <validated-skill-path>
74
56
 
75
57
  leerness library guide [path]
76
- leerness library status <path>
77
58
  leerness library validate <path> [--strict-ai]
78
59
  leerness library verify <path> --ai --reviewer leerness-ai
79
- leerness library build <path> [--out ./dist] [--package leerness-skill-name]
80
- leerness library update <path> --from <validated-new-skill-path> [--version 1.2.0]
81
- leerness library merge <source-library> --path <project>
82
- leerness library migrate <path> [--version 1.0.0]
60
+ leerness library build <path>
83
61
  leerness library publish <built-library> --target npm|git [--execute]
84
62
  ```
85
63
 
86
- ## 생성 구조
87
-
88
- ```text
89
- your-project/
90
- ├── AGENTS.md
91
- ├── CLAUDE.md
92
- ├── .cursor/rules/leerness.mdc
93
- ├── .github/copilot-instructions.md
94
- └── .harness/
95
- ├── HARNESS_VERSION
96
- ├── manifest.json
97
- ├── project-brief.md
98
- ├── current-state.md
99
- ├── architecture.md
100
- ├── context-map.md
101
- ├── decisions.md
102
- ├── task-log.md
103
- ├── constraints.md
104
- ├── guardrails.md
105
- ├── design-system.md
106
- ├── feature-contracts.md
107
- ├── testing-strategy.md
108
- ├── review-checklist.md
109
- ├── release-checklist.md
110
- ├── session-handoff.md
111
- ├── AX_SKILL_LIBRARY_GUIDE.md
112
- ├── skills/
113
- ├── library/
114
- └── archive/
115
- ```
116
-
117
-
118
- ## 한글 스킬 라이브러리 표시
119
-
120
- Leerness 1.2.0부터 `leerness skill list`는 스킬의 한글명, 가능한 작업, 최종 업데이트일, AI 검증 상태를 함께 표시합니다.
64
+ 작업 유형 라우팅 확인:
121
65
 
122
66
  ```bash
123
- leerness skill list
124
- leerness skill info ai-verified-skill-publisher
67
+ leerness route release
68
+ leerness route feature
69
+ leerness route migration
70
+ leerness route new-install
125
71
  ```
126
72
 
127
- ## AI 검증 스킬 업로드 스킬
128
-
129
- 검증된 스킬을 라이브러리화하고 npm/git으로 업로드하는 절차 자체도 스킬로 설치할 수 있습니다.
130
-
131
- ```bash
132
- leerness skill add ai-verified-skill-publisher
133
- ```
134
-
135
- 이 스킬은 성공한 구현 패턴 추출, 한글명/가능 작업/최종 업데이트일 기록, 민감정보 제거, AI 검증 메타데이터 생성, strict-ai 검증, dry-run 확인, 사용자 승인 후 `--execute` 업로드 흐름을 안내합니다.
136
-
137
- ## AX 최적화 가이드
138
-
139
- 설치하면 AI 에이전트가 바로 읽을 수 있는 가이드가 생성됩니다.
73
+ ## 생성되는 핵심 파일
140
74
 
141
75
  ```text
142
- .harness/AX_SKILL_LIBRARY_GUIDE.md
76
+ .harness/
77
+ project-brief.md # 프로젝트 목적/사용자/성공 기준
78
+ current-state.md # 현재 상태/다음 작업/블로커
79
+ architecture.md # 구조/모듈/데이터 흐름
80
+ context-map.md # 기능별 참조 파일 지도
81
+ decisions.md # 결정 로그
82
+ guardrails.md # 금지사항/보안/민감영역 규칙
83
+ design-system.md # UI/UX/컴포넌트 일관성
84
+ feature-contracts.md # 기능 입력/출력/상태/오류 계약
85
+ testing-strategy.md # 검증 전략
86
+ release-checklist.md # 배포/npm/git/환경변수/롤백 조건
87
+ session-handoff.md # 다음 세션 인수인계
88
+ context-routing.md # 작업 유형별 읽기/갱신 라우팅
89
+ writeback-policy.md # 어떤 정보를 어디에 기록할지
90
+ task-type-map.md # 사용자 요청 → 작업 유형 매핑
91
+ AX_MIGRATION_GUIDE.md # AI용 구버전 마이그레이션 가이드
92
+ AX_NEW_PROJECT_GUIDE.md # AI용 신규 설치/프로젝트 반영 가이드
93
+ AX_SKILL_LIBRARY_GUIDE.md # AI용 스킬 라이브러리 가이드
143
94
  ```
144
95
 
145
- 문서는 다음 작업을 AI 안전하게 수행하도록 안내합니다.
96
+ 핵심 파일에는 `readWhen`, `updateWhen`, `doNotStore` 메타데이터가 들어갑니다. AI 정보를 기준으로 파일을 참조하고 갱신해야 합니다.
146
97
 
147
- - 검증된 스킬 학습
148
- - 스킬 데이터 정규화
149
- - 민감정보 스캔
150
- - AI 검증 메타데이터 기록
151
- - 라이브러리 빌드
152
- - npm/git 업로드 dry-run
153
- - 실제 업로드 승인 흐름
154
- - 업데이트 시 재검증 강제
155
- - 스킬 병합과 마이그레이션
98
+ ## AGENTS.md의 역할
156
99
 
157
- ## AI 검증 게이트
100
+ `AGENTS.md`는 단순 지침 파일이 아니라 AI 작업 라우터입니다.
158
101
 
159
- 스킬 라이브러리는 AI 검증 메타데이터가 있어야 업로드할 수 있습니다.
102
+ 모든 작업은 다음 순서를 따릅니다.
160
103
 
161
- ```bash
162
- leerness library verify ./my-skill --ai --reviewer leerness-ai
163
- leerness library validate ./my-skill --strict-ai
164
- leerness library build ./my-skill
165
- leerness library publish ./my-skill/dist/my-skill --target npm --execute
166
- ```
167
-
168
- `library publish`는 기본값이 dry-run입니다. 실제 업로드는 `--execute`가 있을 때만 실행됩니다.
104
+ 1. 작업 유형을 분류한다.
105
+ 2. `.harness/context-routing.md`와 `.harness/task-type-map.md`를 읽는다.
106
+ 3. 작업 유형별 필수 파일을 읽는다.
107
+ 4. 작업을 수행한다.
108
+ 5. `.harness/writeback-policy.md`에 따라 필요한 파일을 갱신한다.
109
+ 6. `current-state.md`, `task-log.md`, `session-handoff.md`를 최신화한다.
169
110
 
111
+ ## AX 마이그레이션 가이드
170
112
 
171
- ## 검증된 스킬팩 업로드 인증
113
+ 구버전 Leerness, project-harness, 자체 AGENTS/CLAUDE 문서가 있는 프로젝트는 다음 파일을 기준으로 AI가 마이그레이션합니다.
172
114
 
173
- `leerness library publish ... --execute`는 실제 업로드 전에 access token을 확인합니다.
174
-
175
- 우선순위는 다음과 같습니다.
176
-
177
- 1. 명시한 환경변수: `--token-env LEERNESS_NPM_TOKEN`
178
- 2. npm: `LEERNESS_NPM_TOKEN`, `NPM_TOKEN`, `NODE_AUTH_TOKEN`
179
- 3. Git/GitHub: `LEERNESS_GIT_TOKEN`, `LEERNESS_GITHUB_TOKEN`, `GITHUB_TOKEN`, `GH_TOKEN`
180
- 4. 프로젝트 로컬 설정: `.harness/skill-publish.local.json`
181
- 5. 위 항목이 없으면 업로드 직전에 토큰 입력 요구
115
+ ```text
116
+ .harness/AX_MIGRATION_GUIDE.md
117
+ ```
182
118
 
183
- 로컬 설정 예시:
119
+ 가이드는 다음을 지시합니다.
184
120
 
185
- ```json
186
- {
187
- "publishAuth": {
188
- "npmTokenEnv": "LEERNESS_NPM_TOKEN",
189
- "gitTokenEnv": "LEERNESS_GITHUB_TOKEN",
190
- "gitRemoteUrl": "https://github.com/gugu9999gu/leerness"
191
- }
192
- }
193
- ```
121
+ - 기존 하네스/지침 파일 백업
122
+ - legacy 내용의 새 목적지 매핑
123
+ - 충돌되는 규칙 처리
124
+ - 민감정보 제거
125
+ - 새 Context Routing/Writeback Policy 생성
126
+ - 마이그레이션 후 검증 및 session-handoff 갱신
194
127
 
195
- `.harness/skill-publish.local.json`은 `.gitignore`에 포함됩니다. 실제 토큰값을 저장하기보다 토큰이 들어있는 환경변수 이름만 저장하는 방식을 권장합니다.
128
+ ## AX 신규 설치 가이드
196
129
 
197
- Git 업로드 기본 저장소 경로는 다음과 같습니다.
130
+ 이미 진행 중인 프로젝트에 처음 Leerness를 설치했다면 다음 파일을 기준으로 프로젝트 내용을 반영합니다.
198
131
 
199
132
  ```text
200
- https://github.com/gugu9999gu/leerness
133
+ .harness/AX_NEW_PROJECT_GUIDE.md
201
134
  ```
202
135
 
203
- ## 스킬 메타데이터
204
-
205
- 각 스킬에는 최종 업데이트 날짜와 검증 상태가 표시됩니다.
206
-
207
- ```json
208
- {
209
- "name": "commerce-api-coupang",
210
- "version": "1.0.0",
211
- "lastUpdated": "2026-04-28",
212
- "lastUpdatedAt": "2026-04-28T00:00:00.000Z",
213
- "verification": {
214
- "status": "passed",
215
- "method": "ai-assisted-review",
216
- "verifiedBy": "leerness-ai",
217
- "verifiedAt": "2026-04-28T00:00:00.000Z"
218
- }
219
- }
220
- ```
221
-
222
- ## 민감정보 원칙
223
-
224
- 스킬에는 실제 민감정보를 저장하지 않습니다.
136
+ 가이드는 AI에게 다음을 요구합니다.
225
137
 
226
- 허용:
138
+ - 실제 파일 구조와 프레임워크 파악
139
+ - package/config/route/API/DB/deploy/test 파일 확인
140
+ - project-brief, architecture, context-map, design-system, feature-contracts 채우기
141
+ - release-checklist와 testing-strategy를 실제 프로젝트 기준으로 작성
142
+ - session-handoff에 다음 정확한 작업 기록
227
143
 
228
- ```text
229
- COUPANG_ACCESS_KEY
230
- NAVER_AD_CUSTOMER_ID
231
- GOOGLE_APPLICATION_CREDENTIALS
232
- ```
144
+ ## 스킬 라이브러리
233
145
 
234
- 금지:
146
+ 스킬은 한글명, 가능한 작업, 최종 업데이트일, AI 검증 상태를 표시합니다.
235
147
 
236
- ```text
237
- 실제 access token
238
- 실제 cookie
239
- 실제 password
240
- 고객 개인정보 export
241
- 운영 API 응답 원문
148
+ ```bash
149
+ leerness skill list
150
+ leerness skill info ai-verified-skill-publisher
242
151
  ```
243
152
 
244
- 실제 값은 `.env.local`, GitHub Actions Secrets, Vercel/Firebase/Cloud Run 환경변수처럼 프로젝트 외부의 안전한 저장소에 둡니다.
245
-
246
- ## 권장 작업 루틴
153
+ 검증된 스킬 업로드는 AI 검증 메타데이터가 있어야 하며, 실제 npm/git 업로드에는 토큰 게이트가 적용됩니다.
247
154
 
248
- AI 에이전트에게 작업이 끝날 때 이렇게 요청하세요.
155
+ ## 민감정보 원칙
249
156
 
250
- ```text
251
- 이번 작업 내용을 .harness/current-state.md, .harness/task-log.md, .harness/session-handoff.md에 반영해줘.
252
- 중요한 설계 결정이 있었다면 .harness/decisions.md에도 기록해줘.
253
- UI나 기능 계약이 바뀌었다면 design-system.md 또는 feature-contracts.md도 갱신해줘.
254
- 성공한 구현 패턴은 스킬 후보로 정리해줘.
255
- ```
157
+ Leerness 파일에는 실제 토큰, 비밀번호, 쿠키, private key, 고객 개인정보를 저장하지 않습니다. 환경변수 이름과 secret manager key 이름만 기록합니다.
256
158
 
257
159
  ## 라이선스
258
160
 
package/bin/harness.js CHANGED
@@ -7,7 +7,7 @@ const readline = require('readline');
7
7
  const childProcess = require('child_process');
8
8
  const os = require('os');
9
9
 
10
- const VERSION = '1.2.0';
10
+ const VERSION = '1.3.0';
11
11
  const MARK = '<!-- leerness:managed -->';
12
12
  const MIGRATED = '<!-- leerness:migrated-legacy -->';
13
13
  const PACKAGE_ROOT = path.resolve(__dirname, '..');
@@ -18,10 +18,10 @@ const c = { reset:'\x1b[0m', bold:'\x1b[1m', dim:'\x1b[2m', green:'\x1b[32m', ye
18
18
  const legacyItems = ['AI_HARNESS.md','HARNESS.md','PROJECT_CONTEXT.md','CONTEXT.md','ARCHITECTURE.md','DECISIONS.md','CURRENT_STATE.md','TASK_LOG.md','AGENT.md','AGENTS.md','CLAUDE.md','.cursorrules','.cursor/rules/project-rules.mdc','.cursor/rules/leerness.mdc','.github/copilot-instructions.md','docs/guideline.md','docs/history.md','.ai','harness','.harness'];
19
19
 
20
20
  const coreFiles = {
21
- 'AGENTS.md': [MARK,'# {{PROJECT}} AI Agent Harness','','Agent = Model + Harness.','','## Read Order','1. .harness/project-brief.md','2. .harness/current-state.md','3. .harness/architecture.md','4. .harness/context-map.md','5. .harness/guardrails.md','6. .harness/skill-index.md','7. .harness/skills-lock.json','','## Operating Rules','- Read project memory before editing.','- Preserve existing architecture, feature contracts, and design system unless the user explicitly asks to change them.','- Use the matching skill from .harness/skills when a task fits a known pattern.','- Keep secrets, tokens, cookies, credentials, and customer private data out of harness files.','- Record variable names only; store real values in .env.local, CI secrets, or cloud secret manager.','- After work, update current-state, task-log, and session-handoff.','- Record important decisions in decisions.md.','','## Skill Library Lifecycle','- Verified successful patterns can be learned with leerness skill learn.','- Skill libraries must pass secret scanning before build/publish/merge.','- npm/git upload is dry-run by default; --execute is required for real upload.','','## Response Contract','- Summary','- Files changed','- Verification','- Risks or assumptions','- Next step','{{LEGACY_AGENT}}',''].join('\n'),
22
- 'CLAUDE.md': [MARK,'# Claude Code Instructions','','Use AGENTS.md as the source of truth. Before editing, read .harness/current-state.md, architecture.md, context-map.md, guardrails.md, skills-lock.json, and the matching skill file.',''].join('\n'),
23
- '.cursor/rules/leerness.mdc': [MARK,'---','alwaysApply: true','---','Read AGENTS.md first. Follow .harness project memory, installed skills, design-system, feature-contracts, and guardrails.',''].join('\n'),
24
- '.github/copilot-instructions.md': [MARK,'# GitHub Copilot Instructions','','Use AGENTS.md and .harness/ as the project memory. Preserve architecture, feature contracts, security rules, and UI consistency.',''].join('\n'),
21
+ 'AGENTS.md': [MARK,'# {{PROJECT}} AI Agent Harness','','Agent = Model + Leerness Harness.','','## Core Rule','Before editing, route the task. Read `.harness/context-routing.md` and use `leerness route <task-type>` when the task type is unclear.','','## Universal Read Order','1. .harness/project-brief.md','2. .harness/current-state.md','3. .harness/context-routing.md','4. .harness/writeback-policy.md','5. .harness/task-type-map.md','6. .harness/context-map.md','7. .harness/guardrails.md','8. .harness/skills-lock.json','','## Task Routing','- Feature/API work: read architecture.md, feature-contracts.md, context-map.md, skills/feature-implementation.md.','- UI/design work: read design-system.md, feature-contracts.md, skills/ui-consistency.md.','- Debugging: read task-log.md, current-state.md, skills/debugging.md, related feature contract.','- Refactoring: read architecture.md, decisions.md, guardrails.md, skills/refactoring.md.','- Release/deploy: read release-checklist.md, testing-strategy.md, current-state.md, decisions.md.','- Documentation/context work: read writeback-policy.md and update the correct memory files.','- Skill/library work: read AX_SKILL_LIBRARY_GUIDE.md and skills/ai-verified-skill-publisher when installed.','','## Writeback Rules','- Always update current-state.md, task-log.md, and session-handoff.md after meaningful work.','- Update decisions.md when a structural, technology, API, schema, deployment, or irreversible decision is made.','- Update feature-contracts.md when input/output/state/error behavior changes.','- Update design-system.md when UI rules, components, layout, spacing, or states change.','- Update release-checklist.md when deployment, environment variables, rollback, CI, npm, or git release requirements change.','- Update context-map.md when important files, modules, routes, commands, or ownership areas change.','- Update project-brief.md only when product purpose, target users, success criteria, or project direction changes.','','## Operating Rules','- Preserve existing architecture, feature contracts, and design system unless the user explicitly asks to change them.','- Use the matching skill from .harness/skills when a task fits a known pattern.','- Keep secrets, tokens, cookies, credentials, and customer private data out of harness files.','- Record variable names only; store real values in .env.local, CI secrets, or cloud secret manager.','','## Response Contract','- Task type and files consulted','- Summary','- Files changed','- Verification','- Memory files updated','- Risks or assumptions','- Next step','{{LEGACY_AGENT}}',''].join('\n'),
22
+ 'CLAUDE.md': [MARK,'# Claude Code Instructions','','Use AGENTS.md as the source of truth. Route every task through .harness/context-routing.md and .harness/task-type-map.md. Before editing, read current-state.md, writeback-policy.md, context-map.md, guardrails.md, skills-lock.json, and the matching skill file.',''].join('\n'),
23
+ '.cursor/rules/leerness.mdc': [MARK,'---','alwaysApply: true','---','Read AGENTS.md first. Follow .harness/context-routing.md, writeback-policy.md, installed skills, design-system, feature-contracts, and guardrails.',''].join('\n'),
24
+ '.github/copilot-instructions.md': [MARK,'# GitHub Copilot Instructions','','Use AGENTS.md and .harness/ as the project memory. Route the task with context-routing.md, then preserve architecture, feature contracts, security rules, and UI consistency.',''].join('\n'),
25
25
  '.gitignore': ['# Leerness local secrets','.env','.env.local','*.secret.json','.harness/skill-config.local.json','.harness/skill-publish.local.json',''].join('\n'),
26
26
  '.env.example': ['# Leerness environment variable examples','# Copy to .env.local and fill values locally. Never commit real secrets.','',''].join('\n'),
27
27
  '.harness/HARNESS_VERSION': '{{VERSION}}\n',
@@ -29,21 +29,26 @@ const coreFiles = {
29
29
  '.harness/skills-lock.json': '{{SKILLS_LOCK}}\n',
30
30
  '.harness/skill-config.schema.json': [MARK,'{',' "$schema": "https://json-schema.org/draft/2020-12/schema",',' "title": "Leerness Skill Config",',' "type": "object",',' "properties": {',' "envSource": { "type": "string", "default": ".env.local" },',' "installedSkills": { "type": "object" }',' },',' "additionalProperties": true','}',''].join('\n'),
31
31
  '.harness/secret-policy.md': [MARK,'# Secret Policy','','## Never store in harness files','- API keys','- Access tokens','- Refresh tokens','- Passwords','- Cookies','- Private customer data','- Payment credentials','','## Allowed in harness files','- Environment variable names','- Secret manager key names','- Redacted examples','- Fake fixtures','','## Default locations','- Local: .env.local','- CI/CD: GitHub Actions Secrets or provider secrets','- Cloud: Secret Manager or runtime environment variables',''].join('\n'),
32
- '.harness/project-brief.md': [MARK,'# Project Brief: {{PROJECT}}','','## Purpose','','## Success Criteria','','## Users','','## Product Direction','{{LEGACY_BRIEF}}',''].join('\n'),
33
- '.harness/current-state.md': [MARK,'# Current State','','Updated: {{DATE}}','','## Now','- Leerness v{{VERSION}} installed or migrated.','','## Next','- Fill project-brief, context-map, design-system, and feature-contracts.','','## Blockers','- None recorded.','{{LEGACY_STATE}}',''].join('\n'),
34
- '.harness/architecture.md': [MARK,'# Architecture','','## Overview','','## Main Modules','','## Data Flow','','## External Services','','## Boundaries','{{LEGACY_ARCH}}',''].join('\n'),
35
- '.harness/context-map.md': [MARK,'# Context Map','','| Area | Files | Notes |','|---|---|---|','| UI | src/components/**, app/** | Check design-system.md first. |','| API | src/api/**, server/**, functions/** | Preserve response contracts. |','| Data | db/**, firestore/**, prisma/** | Confirm migrations. |','| Tests | test/**, tests/**, __tests__/** | Add or update checks. |',''].join('\n'),
36
- '.harness/decisions.md': [MARK,'# Decision Log','','## Template','','### YYYY-MM-DD — Title','- Decision:','- Reason:','- Alternatives:','- Impact:','{{LEGACY_DECISIONS}}',''].join('\n'),
37
- '.harness/task-log.md': [MARK,'# Task Log','','## {{DATE}}','- Installed Leerness v{{VERSION}}.',''].join('\n'),
32
+ '.harness/project-brief.md': [MARK,'---','leernessRole: project-brief','readWhen: [every-task, planning, product-direction, onboarding]','updateWhen: [purpose-change, user-change, success-criteria-change, product-direction-change]','doNotStore: [secrets, tokens, credentials, raw-customer-data]','---','','# Project Brief: {{PROJECT}}','','## When to read','Read this before meaningful work to understand why the project exists and what success means.','','## When to update','Update only when product purpose, target users, success criteria, scope, or strategic direction changes.','','## Purpose','','## Success Criteria','','## Users','','## Product Direction','{{LEGACY_BRIEF}}',''].join('\n'),
33
+ '.harness/current-state.md': [MARK,'---','leernessRole: current-state','readWhen: [every-task, resume-work, planning, debugging, release]','updateWhen: [after-meaningful-work, blocker-change, next-step-change, status-change]','doNotStore: [secrets, tokens, credentials]','---','','# Current State','','Updated: {{DATE}}','','## When to read','Read at the start of every session to know where the project currently stands.','','## When to update','Update after meaningful work, changed blockers, or changed next steps.','','## Now','- Leerness v{{VERSION}} installed or migrated.','','## Next','- Fill project-brief, context-map, design-system, and feature-contracts.','','## Blockers','- None recorded.','{{LEGACY_STATE}}',''].join('\n'),
34
+ '.harness/architecture.md': [MARK,'---','leernessRole: architecture','readWhen: [feature, refactor, integration, api, database, deployment]','updateWhen: [module-change, data-flow-change, integration-change, boundary-change]','doNotStore: [secrets, credentials]','---','','# Architecture','','## When to read','Read before structural changes, feature work touching multiple modules, integrations, API, database, or deployment changes.','','## When to update','Update when module boundaries, data flow, external services, or ownership changes.','','## Overview','','## Main Modules','','## Data Flow','','## External Services','','## Boundaries','{{LEGACY_ARCH}}',''].join('\n'),
35
+ '.harness/context-map.md': [MARK,'---','leernessRole: context-map','readWhen: [every-task, file-discovery, impact-analysis]','updateWhen: [new-important-file, moved-module, new-route, new-service, ownership-change]','doNotStore: [secrets, tokens]','---','','# Context Map','','## When to read','Read when deciding which files or modules are relevant to a task.','','## When to update','Update when important files, routes, modules, services, or ownership areas change.','','| Area | Files | Notes |','|---|---|---|','| UI | src/components/**, app/** | Check design-system.md first. |','| API | src/api/**, server/**, functions/** | Preserve response contracts. |','| Data | db/**, firestore/**, prisma/** | Confirm migrations. |','| Tests | test/**, tests/**, __tests__/** | Add or update checks. |',''].join('\n'),
36
+ '.harness/decisions.md': [MARK,'---','leernessRole: decisions','readWhen: [architecture, refactor, release, dependency-change, irreversible-change]','updateWhen: [important-decision, tradeoff, architecture-change, dependency-change, rollback-relevant-change]','doNotStore: [secrets, credentials]','---','','# Decision Log','','## When to read','Read before changing architecture, dependencies, deployment, data model, API contracts, or irreversible behavior.','','## When to update','Update when a decision affects future work or explains why an approach was chosen.','','## Template','','### YYYY-MM-DD — Title','- Decision:','- Reason:','- Alternatives:','- Impact:','{{LEGACY_DECISIONS}}',''].join('\n'),
37
+ '.harness/task-log.md': [MARK,'---','leernessRole: task-log','readWhen: [debugging, regression, audit, resume-work]','updateWhen: [after-meaningful-work, bug-fix, release, migration, skill-learning]','doNotStore: [secrets, tokens, private-customer-data]','---','','# Task Log','','## When to read','Read to understand previous work, regressions, attempted fixes, and release/migration history.','','## When to update','Update after meaningful work with what changed and how it was verified.','','## {{DATE}}','- Installed Leerness v{{VERSION}}.',''].join('\n'),
38
38
  '.harness/constraints.md': [MARK,'# Constraints','','- Runtime/framework constraints','- Deployment constraints','- Security/privacy constraints','- Business rules',''].join('\n'),
39
- '.harness/guardrails.md': [MARK,'# Guardrails','','## Never','- Do not perform unrequested large rewrites.','- Do not change public API, database schema, auth, payment, or environment variable names without identifying impact.','- Do not hardcode secrets.','- Do not create a new design pattern when an existing one fits.','','## Always','- Inspect current structure first.','- Make the smallest safe change.','- Verify behavior.','- Update project memory after meaningful changes.',''].join('\n'),
40
- '.harness/design-system.md': [MARK,'# Design System Memory','','## Layout','- Reuse existing spacing, component variants, typography, and breakpoints.','','## Components','| Component | Purpose | Rules |','|---|---|---|','| Button | Primary actions | Reuse existing variants. |','| Card | Grouped content | Keep spacing and radius consistent. |','| Form | Input flows | Include loading, error, and empty states. |',''].join('\n'),
41
- '.harness/feature-contracts.md': [MARK,'# Feature Contracts','','## Template','- Feature:','- Entry point:','- Input:','- Output:','- Error states:','- UI states:','- Related files:','- Tests:',''].join('\n'),
42
- '.harness/testing-strategy.md': [MARK,'# Testing Strategy','','- Unit: pure logic and adapters','- Integration: API, DB, third-party providers','- E2E/manual: key user flows','- Regression: previously fixed bugs and successful skills',''].join('\n'),
43
- '.harness/review-checklist.md': [MARK,'# Review Checklist','','- [ ] Existing architecture preserved','- [ ] Feature contracts respected','- [ ] Design system followed','- [ ] Secrets not exposed','- [ ] Tests or manual verification completed','- [ ] current-state/task-log/session-handoff updated',''].join('\n'),
44
- '.harness/release-checklist.md': [MARK,'# Release Checklist','','- [ ] Build/test passed','- [ ] Env variables confirmed','- [ ] Migration impact checked','- [ ] Rollback path known','- [ ] Release notes prepared',''].join('\n'),
45
- '.harness/session-handoff.md': [MARK,'# Session Handoff','','## Done','-','','## Changed Files','-','','## Decisions','-','','## Risks','-','','## Next Exact Step','-',''].join('\n'),
46
- '.harness/skill-index.md': [MARK,'# Skill Index','','Installed skill libraries are tracked in `.harness/skills-lock.json`.','','## Commands','`leerness skill list` — 한글명/가능 작업/업데이트/검증 상태 표시','`leerness skill add commerce-api`','`leerness skill learn my-skill --from .harness/skills/...`','`leerness library verify .harness/library/my-skill --ai`','`leerness library build .harness/library/my-skill`','`leerness skill add ai-verified-skill-publisher`','`leerness library publish .harness/library/my-skill/dist/my-skill --target npm --execute`','','## Metadata','Every skill should expose version, lastUpdated, lastUpdatedAt, and verification status.',''].join('\n'),
39
+ '.harness/guardrails.md': [MARK,'---','leernessRole: guardrails','readWhen: [every-task, security, auth, payment, db, refactor, release]','updateWhen: [new-risk, repeated-ai-mistake, policy-change, sensitive-area-change]','doNotStore: [secrets, tokens, credentials]','---','','# Guardrails','','## When to read','Read before every task, especially auth, payment, database, security, refactoring, release, or external integration work.','','## When to update','Update when a new risk, repeated mistake, project policy, or sensitive area rule is discovered.','','## Never','- Do not perform unrequested large rewrites.','- Do not change public API, database schema, auth, payment, or environment variable names without identifying impact.','- Do not hardcode secrets.','- Do not create a new design pattern when an existing one fits.','','## Always','- Inspect current structure first.','- Make the smallest safe change.','- Verify behavior.','- Update project memory after meaningful changes.',''].join('\n'),
40
+ '.harness/design-system.md': [MARK,'---','leernessRole: design-system','readWhen: [ui, ux, component, styling, layout, accessibility]','updateWhen: [new-ui-pattern, changed-component-rule, visual-standard-change, state-pattern-change]','doNotStore: [secrets]','---','','# Design System Memory','','## When to read','Read before UI, UX, component, layout, responsive, accessibility, or styling changes.','','## When to update','Update when reusable UI rules, component variants, spacing, states, or accessibility patterns change.','','## Layout','- Reuse existing spacing, component variants, typography, and breakpoints.','','## Components','| Component | Purpose | Rules |','|---|---|---|','| Button | Primary actions | Reuse existing variants. |','| Card | Grouped content | Keep spacing and radius consistent. |','| Form | Input flows | Include loading, error, and empty states. |',''].join('\n'),
41
+ '.harness/feature-contracts.md': [MARK,'---','leernessRole: feature-contracts','readWhen: [feature, api, ui-state, integration, debugging, regression]','updateWhen: [input-change, output-change, state-change, error-change, api-contract-change]','doNotStore: [secrets, raw-private-data]','---','','# Feature Contracts','','## When to read','Read before implementing or changing a feature, API, UI state, integration, or bug fix that touches behavior.','','## When to update','Update when inputs, outputs, states, errors, API contracts, or validation rules change.','','## Template','- Feature:','- Entry point:','- Input:','- Output:','- Error states:','- UI states:','- Related files:','- Tests:',''].join('\n'),
42
+ '.harness/testing-strategy.md': [MARK,'---','leernessRole: testing-strategy','readWhen: [feature, debugging, release, refactor, migration]','updateWhen: [new-test-pattern, changed-critical-flow, recurring-bug, release-risk]','doNotStore: [secrets, private-test-data]','---','','# Testing Strategy','','## When to read','Read before feature, bug fix, refactor, migration, or release work to choose verification scope.','','## When to update','Update when a new test pattern, critical flow, regression risk, or verification standard appears.','','- Unit: pure logic and adapters','- Integration: API, DB, third-party providers','- E2E/manual: key user flows','- Regression: previously fixed bugs and successful skills',''].join('\n'),
43
+ '.harness/review-checklist.md': [MARK,'---','leernessRole: review-checklist','readWhen: [before-final-answer, pull-request, code-review, handoff]','updateWhen: [new-review-risk, repeated-defect, quality-standard-change]','doNotStore: [secrets]','---','','# Review Checklist','','## When to read','Read before finalizing meaningful changes, PRs, reviews, or handoffs.','','## When to update','Update when recurring review failures or new quality gates are discovered.','','- [ ] Existing architecture preserved','- [ ] Feature contracts respected','- [ ] Design system followed','- [ ] Secrets not exposed','- [ ] Tests or manual verification completed','- [ ] current-state/task-log/session-handoff updated',''].join('\n'),
44
+ '.harness/release-checklist.md': [MARK,'---','leernessRole: release-checklist','readWhen: [release, deploy, npm-publish, git-push, ci-cd, env-change]','updateWhen: [deployment-failure, new-env-var, rollback-change, ci-change, publish-rule-change]','doNotStore: [access-tokens, passwords, cookies, private-keys]','---','','# Release Checklist','','## When to read','Read before deployment, npm publish, git push release, CI/CD change, environment variable change, or migration.','','## When to update','Update when a release fails, a new release condition appears, an env var changes, CI/CD changes, or rollback steps change.','','- [ ] Build/test passed','- [ ] Env variables confirmed','- [ ] Migration impact checked','- [ ] Rollback path known','- [ ] Release notes prepared',''].join('\n'),
45
+ '.harness/session-handoff.md': [MARK,'---','leernessRole: session-handoff','readWhen: [resume-work, new-session, handoff]','updateWhen: [end-of-session, interrupted-work, unresolved-risk, next-step-change]','doNotStore: [secrets, tokens]','---','','# Session Handoff','','## When to read','Read at the start of a new AI session or when continuing interrupted work.','','## When to update','Update at the end of meaningful work with the exact next step.','','## Done','-','','## Changed Files','-','','## Decisions','-','','## Risks','-','','## Next Exact Step','-',''].join('\n'),
46
+ '.harness/skill-index.md': [MARK,'---','leernessRole: skill-index','readWhen: [skill, automation, integration, repeated-task, library]','updateWhen: [skill-installed, skill-removed, skill-updated, new-skill-learned]','doNotStore: [secrets, tokens]','---','','# Skill Index','','Installed skill libraries are tracked in `.harness/skills-lock.json`.','','## When to read','Read when a task resembles a known repeated pattern or domain workflow.','','## When to update','Update when skills are installed, removed, updated, learned, or migrated.','','## Commands','`leerness skill list` — 한글명/가능 작업/업데이트/검증 상태 표시','`leerness skill info <name>`','`leerness skill add commerce-api`','`leerness skill learn my-skill --from .harness/skills/...`','`leerness library verify .harness/library/my-skill --ai`','`leerness library build .harness/library/my-skill`','`leerness skill add ai-verified-skill-publisher`','`leerness library publish .harness/library/my-skill/dist/my-skill --target npm --execute`','','## Metadata','Every skill should expose version, displayNameKo, capabilities, lastUpdated, lastUpdatedAt, and verification status.',''].join('\n'),
47
+ '.harness/context-routing.md': [MARK,'---','leernessRole: context-routing','readWhen: [every-task, task-classification, before-editing]','updateWhen: [new-task-type, changed-routing, new-required-file, repeated-missed-context]','doNotStore: [secrets, tokens]','---','','# Context Routing','','Use this file to decide which memory files to read before work and which files to update after work.','','## Universal baseline','','Read before every meaningful task:','- project-brief.md','- current-state.md','- context-routing.md','- writeback-policy.md','- task-type-map.md','- context-map.md','- guardrails.md','','## Task routes','','### feature','Read: architecture.md, feature-contracts.md, context-map.md, skills/feature-implementation.md, testing-strategy.md','Update: current-state.md, task-log.md, session-handoff.md, feature-contracts.md, context-map.md when file map changes','','### ui','Read: design-system.md, feature-contracts.md, context-map.md, skills/ui-consistency.md','Update: design-system.md, feature-contracts.md, current-state.md, task-log.md, session-handoff.md','','### debugging','Read: current-state.md, task-log.md, feature-contracts.md, testing-strategy.md, skills/debugging.md','Update: task-log.md, current-state.md, session-handoff.md, testing-strategy.md when regression coverage changes','','### refactor','Read: architecture.md, decisions.md, guardrails.md, testing-strategy.md, skills/refactoring.md','Update: architecture.md, decisions.md when reasoning matters, task-log.md, session-handoff.md','','### release','Read: release-checklist.md, testing-strategy.md, current-state.md, decisions.md, secret-policy.md','Update: release-checklist.md, task-log.md, current-state.md, session-handoff.md','','### migration','Read: AX_MIGRATION_GUIDE.md, architecture.md, decisions.md, release-checklist.md, testing-strategy.md','Update: current-state.md, task-log.md, session-handoff.md, context-map.md, release-checklist.md, decisions.md when needed','','### new-install','Read: AX_NEW_PROJECT_GUIDE.md, project-brief.md, context-map.md, guardrails.md','Update: project-brief.md, architecture.md, context-map.md, design-system.md, feature-contracts.md, current-state.md','','### skill-library','Read: AX_SKILL_LIBRARY_GUIDE.md, skill-index.md, skills-lock.json, secret-policy.md','Update: skill-index.md, skills-lock.json, task-log.md, session-handoff.md','',''].join('\n'),
48
+ '.harness/writeback-policy.md': [MARK,'---','leernessRole: writeback-policy','readWhen: [every-task, documentation, memory-update, handoff]','updateWhen: [new-memory-rule, repeated-missing-update, changed-document-role]','doNotStore: [secrets, tokens]','---','','# Writeback Policy','','This file defines where project knowledge must be recorded.','','| Information | Write to | Notes |','|---|---|---|','| Current progress, blockers, next step | current-state.md | Update after meaningful work. |','| Work performed and verification | task-log.md | Date-based factual log. |','| Next-session handoff | session-handoff.md | Keep exact next action. |','| Structural decisions and tradeoffs | decisions.md | Include reason and impact. |','| File/module map | context-map.md | Update when files/routes/services change. |','| Feature behavior | feature-contracts.md | Inputs, outputs, states, errors, tests. |','| UI/UX rules | design-system.md | Reusable component and state rules. |','| Release/env/rollback gates | release-checklist.md | Update after publish/deploy findings. |','| Testing patterns | testing-strategy.md | Regression and verification strategy. |','| Repeated successful workflows | skill-index.md and .harness/skills/ | Never include secret values. |','','## Do not record','- Actual access tokens, passwords, cookies, private keys, customer private data','- Raw production exports unless redacted and explicitly allowed','- Temporary guesses that were disproved; move those to task-log as failed attempts if useful','',''].join('\n'),
49
+ '.harness/task-type-map.md': [MARK,'---','leernessRole: task-type-map','readWhen: [every-task, task-classification, ambiguous-request]','updateWhen: [new-task-wording, new-domain-workflow, repeated-misclassification]','doNotStore: [secrets, tokens]','---','','# Task Type Map','','Map user requests to task types, then follow context-routing.md.','','| User request pattern | Task type | First files to consult |','|---|---|---|','| 새 기능, 구현, API 추가 | feature | feature-contracts.md, architecture.md |','| 디자인 맞춰줘, UI 수정, 반응형 | ui | design-system.md, feature-contracts.md |','| 오류, 에러, 안 됨, 원인 | debugging | task-log.md, current-state.md, debugging skill |','| 구조 개선, 리팩토링 | refactor | architecture.md, decisions.md, guardrails.md |','| 배포, npm publish, git push, 릴리즈 | release | release-checklist.md, testing-strategy.md |','| 구버전 하네스 반영, 이전 파일 정리 | migration | AX_MIGRATION_GUIDE.md, context-routing.md |','| 처음 설치, 기존 프로젝트 반영 | new-install | AX_NEW_PROJECT_GUIDE.md, project-brief.md |','| 스킬로 저장, 스킬 업로드, 라이브러리화 | skill-library | AX_SKILL_LIBRARY_GUIDE.md, skill-index.md |','| 문서 갱신, 맥락 정리 | documentation | writeback-policy.md, context-routing.md |','',''].join('\n'),
50
+ '.harness/AX_MIGRATION_GUIDE.md': [MARK,'---','leernessRole: ax-migration-guide','readWhen: [migration, legacy-harness, old-version, upgrade]','updateWhen: [migration-rule-change, legacy-pattern-change, failed-migration]','doNotStore: [secrets, tokens, credentials]','---','','# AX Migration Guide for AI Agents','','Use this guide when upgrading an existing project that already has AGENTS.md, CLAUDE.md, .harness/, docs/guideline.md, old project-harness files, or older Leerness output.','','## Goal','Migrate without losing project memory. Preserve useful legacy content, remove ambiguity about source-of-truth files, and create routing/writeback rules so future work references the right files.','','## Required steps','1. Run `leerness migrate --dry-run` and inspect detected legacy files.','2. Back up existing harness files under `.harness/archive/legacy-migration-*`.','3. Generate or update context-routing.md, writeback-policy.md, task-type-map.md, AGENTS.md, and AX guides.','4. Move useful old content into the correct files: project purpose to project-brief.md, architecture to architecture.md, task history to task-log.md/current-state.md, release notes to release-checklist.md.','5. Replace stale instruction files with pointers to AGENTS.md and .harness/context-routing.md when safe.','6. Run `leerness status` and `leerness verify`.','7. Update session-handoff.md with what was migrated and what remains.','','## Mapping legacy content','| Legacy content | New destination |','|---|---|','| Project goal / product context | project-brief.md |','| Architecture / module map | architecture.md, context-map.md |','| Old task history | task-log.md, current-state.md |','| Release/deploy notes | release-checklist.md |','| AI rules / prompts | AGENTS.md, guardrails.md, context-routing.md |','| Successful repeated workflow | .harness/skills/ or skill library candidate |','','## Safety rules','- Do not delete legacy files before archive exists.','- Do not copy secret values into harness files. Replace with environment variable names.','- Do not merge contradictory rules silently; record conflict in decisions.md or session-handoff.md.','- Keep the current active source of truth obvious: AGENTS.md + .harness/context-routing.md.','',''].join('\n'),
51
+ '.harness/AX_NEW_PROJECT_GUIDE.md': [MARK,'---','leernessRole: ax-new-project-guide','readWhen: [new-install, onboarding, first-run, existing-project-analysis]','updateWhen: [onboarding-rule-change, project-discovery-change, new-baseline-file]','doNotStore: [secrets, tokens, credentials]','---','','# AX New Project Installation Guide for AI Agents','','Use this guide after installing Leerness into a new or ongoing project. The goal is to reflect the real project, not leave generic templates.','','## Required project discovery','1. Identify package/framework/runtime from package.json, lockfiles, config files, and folder structure.','2. Identify entry points, routes, API handlers, DB/schema files, deployment config, test commands, and UI system.','3. Fill project-brief.md with purpose, users, success criteria, and product direction.','4. Fill architecture.md with modules, boundaries, data flow, and external services.','5. Fill context-map.md with exact file paths for UI, API, data, auth, deploy, tests, and docs.','6. Fill design-system.md from existing UI components and patterns.','7. Fill feature-contracts.md for important flows and APIs.','8. Fill release-checklist.md from actual deployment/npm/git/CI requirements.','9. Fill testing-strategy.md from actual scripts and manual flows.','10. Update current-state.md and session-handoff.md with the next exact action.','','## AI behavior','- Do not leave placeholders when the project contains enough information.','- Do not invent architecture; mark unknowns explicitly.','- Prefer exact file paths over vague folder names.','- Store environment variable names only, never values.','- When a repeated successful workflow is found, propose a skill candidate.','','## Completion checklist','- [ ] `leerness route feature` returns useful guidance.','- [ ] project-brief.md is specific to this project.','- [ ] context-map.md contains real paths.','- [ ] release-checklist.md matches actual deploy/publish flow.','- [ ] AGENTS.md directs future AI work to the right files.','- [ ] session-handoff.md has the next exact step.','',''].join('\n'),
47
52
  '.harness/AX_SKILL_LIBRARY_GUIDE.md': [MARK,
48
53
  '# Leerness AX Skill Library Guide',
49
54
  '',
@@ -170,7 +175,7 @@ function migrateSkillLibrary(dir,flags){ dir=path.resolve(dir||process.cwd()); i
170
175
  function publishSkillLibrary(dir,flags){ dir=path.resolve(dir||process.cwd()); const target=String(flags.target||'npm'); const execute=Boolean(flags.execute); const check=validateSkillLibrary(dir,{silent:false}); if(!check.ok){ process.exitCode=1; return; } if(target==='npm'){ if(!exists(path.join(dir,'package.json'))){ warn('package.json이 없습니다. 먼저 build를 실행하세요.'); info('leerness library build '+dir); process.exitCode=1; return; } const args=['publish','--access','public'].concat(flags.registry?['--registry',flags.registry]:[]); if(!execute){ info('[dry-run] 실행 예정: (cd '+dir+') npm '+args.join(' ')); info('실제 배포는 --execute를 붙이세요.'); return; } const r=childProcess.spawnSync('npm',args,{cwd:dir,stdio:'inherit',shell:process.platform==='win32'}); process.exitCode=r.status||0; return; } if(target==='git'){ const repo=flags.repo; const branch=flags.branch||'main'; const message=flags.message||('Publish skill library '+check.meta.name+'@'+(check.meta.version||'0.1.0')); if(!execute){ info('[dry-run] git target repo: '+(repo||'(current repo)')); info('[dry-run] branch: '+branch); info('[dry-run] commit message: '+message); info('실제 push는 --execute를 붙이세요.'); return; } const run=(cmd,args)=>{ const r=childProcess.spawnSync(cmd,args,{cwd:dir,stdio:'inherit',shell:process.platform==='win32'}); if(r.status) process.exit(r.status); }; if(repo&&!exists(path.join(dir,'.git'))){ run('git',['init']); run('git',['remote','add','origin',repo]); } run('git',['add','.']); run('git',['commit','-m',message]); run('git',['branch','-M',branch]); run('git',['push','-u','origin',branch]); return; } fail('지원하지 않는 publish target: '+target); process.exitCode=1; }
171
176
  function libraryCommand(args,flags){ const sub=args[1]||'help'; if(sub==='help'){ log(['Leerness Skill Library Commands','',' leerness skill learn <name> --from .harness/skills/<name> [--out ./library/<name>]',' leerness library validate <path>',' leerness library build <path> [--out ./dist] [--package leerness-skill-name]',' leerness library merge <source-library> [--path <project>]',' leerness library migrate <path> [--version 1.0.0]',' leerness library publish <built-library> --target npm|git [--execute] [--repo https://github.com/gugu9999gu/leerness]','','기본 publish는 dry-run입니다. 실제 npm/git 업로드는 --execute가 필요합니다.',''].join('\n')); return; } if(sub==='validate') return validateSkillLibrary(args[2]||process.cwd(),{silent:false}); if(sub==='build') return buildSkillLibrary(args[2]||process.cwd(),flags); if(sub==='merge') return mergeSkillLibrary(flags.path||process.cwd(),args[2]||flags.source,flags); if(sub==='migrate') return migrateSkillLibrary(args[2]||process.cwd(),flags); if(sub==='publish'||sub==='upload') return publishSkillLibrary(args[2]||process.cwd(),flags); fail('알 수 없는 library 명령: '+sub); process.exitCode=1; }
172
177
  function skillCommand(args,flags){ const sub=args[1]||'list'; const root=path.resolve(flags.path||process.cwd()); if(sub==='learn'){ flags.name=args[2]||flags.name; return learnSkillLibrary(root,flags); } if(sub==='library') return libraryCommand(['library'].concat(args.slice(2)),flags); if(sub==='list'){ banner(); log('사용 가능한 스킬 라이브러리'); for(const p of listSkillPacks()){ log('- '+p.name+'@'+p.version+': '+p.title); log(' '+p.description); if((p.requiresEnv||[]).length) log(' env: '+(p.requiresEnv||[]).join(', ')); } return; } const name=args[2]; if(!name){ fail('스킬 이름이 필요합니다. 예: leerness skill add commerce-api'); return; } if(sub==='add'||sub==='install') return installSkill(root,name,Boolean(flags['dry-run'])); if(sub==='remove'||sub==='rm') return removeSkill(root,name); if(sub==='update') return installSkill(root,name,false); fail('알 수 없는 skill 명령: '+sub); }
173
- function help(){ log(['Leerness v'+VERSION,'','Usage:',' leerness init [path] [--yes] [--skills office,commerce-api|recommended|all]',' leerness migrate [path] [--dry-run]',' leerness status [path]',' leerness verify [path]','','Skills:',' leerness skill list',' leerness skill info <name>',' leerness skill add <name> [--path <project>]',' leerness skill remove <name> [--path <project>]',' leerness skill update <name> [--path <project>]',' leerness skill learn <name> --from <validated-skill-path> [--out <library-path>]','','Skill library lifecycle:',' leerness library validate <path>',' leerness library build <path> [--out ./dist] [--package leerness-skill-name]',' leerness library merge <source-library> [--path <project>]',' leerness library migrate <path> [--version 1.0.0]',' leerness library publish <built-library> --target npm|git [--execute] [--repo https://github.com/gugu9999gu/leerness]',' leerness --version','','Examples:',' npx leerness init --skills recommended',' npx leerness skill learn coupang-order-sync --from .harness/skills/commerce-api/order-sync.md',' npx leerness library build .harness/library/coupang-order-sync',' npx leerness library publish .harness/library/coupang-order-sync/dist/coupang-order-sync --target npm --execute',''].join('\n')); }
178
+ function help(){ log(['Leerness v'+VERSION,'','Usage:',' leerness init [path] [--yes] [--skills office,commerce-api|recommended|all]',' leerness migrate [path] [--dry-run]',' leerness status [path]',' leerness verify [path]',' leerness route <feature|ui|debugging|refactor|release|migration|new-install|skill-library|documentation>','','Skills:',' leerness skill list',' leerness skill info <name>',' leerness skill add <name> [--path <project>]',' leerness skill remove <name> [--path <project>]',' leerness skill update <name> [--path <project>]',' leerness skill learn <name> --from <validated-skill-path> [--out <library-path>]','','Skill library lifecycle:',' leerness library validate <path>',' leerness library build <path> [--out ./dist] [--package leerness-skill-name]',' leerness library merge <source-library> [--path <project>]',' leerness library migrate <path> [--version 1.0.0]',' leerness library publish <built-library> --target npm|git [--execute] [--repo https://github.com/gugu9999gu/leerness]',' leerness --version','','Examples:',' npx leerness init --skills recommended',' npx leerness skill learn coupang-order-sync --from .harness/skills/commerce-api/order-sync.md',' npx leerness library build .harness/library/coupang-order-sync',' npx leerness library publish .harness/library/coupang-order-sync/dist/coupang-order-sync --target npm --execute',''].join('\n')); }
174
179
 
175
180
 
176
181
  function nowIso(){ return new Date().toISOString(); }
@@ -388,7 +393,7 @@ function libraryGuide(root,flags={}){
388
393
  }
389
394
  function libraryCommand(args,flags){
390
395
  const sub=args[1]||'help';
391
- if(sub==='help'){ log(['Leerness Skill Library Commands','',' leerness library guide [project-path]',' leerness library status <path>',' leerness library validate <path> [--strict-ai]',' leerness library verify <path> --ai --reviewer leerness-ai',' leerness library build <path> [--out ./dist] [--package leerness-skill-name]',' leerness library update <path> --from <validated-new-skill-path> [--version 1.2.0]',' leerness library merge <source-library> [--path <project>]',' leerness library migrate <path> [--version 1.0.0]',' leerness library publish <built-library> --target npm|git [--execute] [--repo https://github.com/gugu9999gu/leerness]','','업로드는 AI 검증 메타데이터가 있는 스킬만 가능하며 기본 publish는 dry-run입니다. --execute 시 npm/git 토큰이 필요합니다.',''].join('\n')); return; }
396
+ if(sub==='help'){ log(['Leerness Skill Library Commands','',' leerness library guide [project-path]',' leerness library status <path>',' leerness library validate <path> [--strict-ai]',' leerness library verify <path> --ai --reviewer leerness-ai',' leerness library build <path> [--out ./dist] [--package leerness-skill-name]',' leerness library update <path> --from <validated-new-skill-path> [--version 1.3.0]',' leerness library merge <source-library> [--path <project>]',' leerness library migrate <path> [--version 1.0.0]',' leerness library publish <built-library> --target npm|git [--execute] [--repo https://github.com/gugu9999gu/leerness]','','업로드는 AI 검증 메타데이터가 있는 스킬만 가능하며 기본 publish는 dry-run입니다. --execute 시 npm/git 토큰이 필요합니다.',''].join('\n')); return; }
392
397
  if(sub==='guide') return libraryGuide(args[2]||flags.path||process.cwd(),flags);
393
398
  if(sub==='status') return libraryStatus(args[2]||process.cwd());
394
399
  if(sub==='validate') return validateSkillLibrary(args[2]||process.cwd(),{silent:false,strictAi:Boolean(flags['strict-ai']||flags.strictAi)});
@@ -448,7 +453,34 @@ function status(root){
448
453
  const names=Object.keys(lock.installedSkills||{}); log('설치 스킬: '+(names.length?names.join(', '):'없음'));
449
454
  for(const n of names){ const m=lock.installedSkills[n]; log(' - '+n+'@'+(m.version||'?')+' · updated '+(m.lastUpdated||'unknown')+' · '+(m.verificationStatus||'unknown')); }
450
455
  }
451
- function help(){ log(['Leerness v'+VERSION,'','Usage:',' leerness init [path] [--yes] [--skills office,commerce-api|recommended|all]',' leerness migrate [path] [--dry-run]',' leerness status [path]',' leerness verify [path]','','Skills:',' leerness skill list',' leerness skill add <name> [--path <project>]',' leerness skill remove <name> [--path <project>]',' leerness skill update <name> [--path <project>]',' leerness skill learn <name> --from <validated-skill-path> [--out <library-path>]','','Skill library lifecycle:',' leerness library guide [path]',' leerness library status <path>',' leerness library validate <path> [--strict-ai]',' leerness library verify <path> --ai --reviewer leerness-ai',' leerness library build <path> [--out ./dist] [--package leerness-skill-name]',' leerness library update <path> --from <validated-new-skill-path> [--version 1.2.0]',' leerness library merge <source-library> [--path <project>]',' leerness library migrate <path> [--version 1.0.0]',' leerness library publish <built-library> --target npm|git [--execute] [--repo https://github.com/gugu9999gu/leerness]',' leerness --version','','Examples:',' npx leerness init --skills recommended',' npx leerness skill learn coupang-order-sync --from .harness/skills/commerce-api/order-sync.md',' npx leerness library verify .harness/library/coupang-order-sync --ai --reviewer leerness-ai',' npx leerness library build .harness/library/coupang-order-sync',' npx leerness library publish .harness/library/coupang-order-sync/dist/coupang-order-sync --target npm --execute',''].join('\n')); }
452
456
 
453
- async function main(){ const parsed=parseArgs(process.argv.slice(2)); const args=parsed.positionals; const flags=parsed.flags; if(flags.version||flags.v){ log(VERSION); return; } if(flags.help||flags.h){ help(); return; } const cmd=args[0]||'init'; if(cmd==='init') return init(args[1]||process.cwd(),flags); if(cmd==='migrate') return migrate(args[1]||process.cwd(),flags); if(cmd==='status') return status(args[1]||process.cwd()); if(cmd==='verify') return verify(args[1]||process.cwd()); if(cmd==='skill') return skillCommand(args,flags); if(cmd==='library') return libraryCommand(args,flags); help(); process.exitCode=1; }
457
+ const taskRouteData = {
458
+ feature: {read:['project-brief.md','current-state.md','context-routing.md','architecture.md','context-map.md','feature-contracts.md','skills/feature-implementation.md','testing-strategy.md'], update:['current-state.md','task-log.md','session-handoff.md','feature-contracts.md','context-map.md when important paths change']},
459
+ ui: {read:['project-brief.md','current-state.md','design-system.md','feature-contracts.md','context-map.md','skills/ui-consistency.md'], update:['design-system.md','feature-contracts.md','current-state.md','task-log.md','session-handoff.md']},
460
+ debugging: {read:['current-state.md','task-log.md','feature-contracts.md','testing-strategy.md','skills/debugging.md','context-map.md'], update:['task-log.md','current-state.md','session-handoff.md','testing-strategy.md when regression coverage changes']},
461
+ refactor: {read:['architecture.md','decisions.md','guardrails.md','testing-strategy.md','skills/refactoring.md'], update:['architecture.md when structure changes','decisions.md when reasoning matters','task-log.md','session-handoff.md']},
462
+ release: {read:['release-checklist.md','testing-strategy.md','current-state.md','decisions.md','secret-policy.md'], update:['release-checklist.md','task-log.md','current-state.md','session-handoff.md']},
463
+ migration: {read:['AX_MIGRATION_GUIDE.md','context-routing.md','writeback-policy.md','architecture.md','decisions.md','release-checklist.md'], update:['current-state.md','task-log.md','session-handoff.md','context-map.md','release-checklist.md','decisions.md when needed']},
464
+ 'new-install': {read:['AX_NEW_PROJECT_GUIDE.md','project-brief.md','context-map.md','guardrails.md','package/config files'], update:['project-brief.md','architecture.md','context-map.md','design-system.md','feature-contracts.md','release-checklist.md','testing-strategy.md','current-state.md','session-handoff.md']},
465
+ 'skill-library': {read:['AX_SKILL_LIBRARY_GUIDE.md','skill-index.md','skills-lock.json','secret-policy.md'], update:['skill-index.md','skills-lock.json','task-log.md','session-handoff.md']},
466
+ documentation: {read:['writeback-policy.md','context-routing.md','task-type-map.md'], update:['the specific memory file defined by writeback-policy.md','task-log.md','session-handoff.md']}
467
+ };
468
+ function routeCommand(task){
469
+ banner();
470
+ if(!task||task==='list'){
471
+ log('사용 가능한 task type: '+Object.keys(taskRouteData).join(', '));
472
+ log('예: leerness route release');
473
+ return;
474
+ }
475
+ const r=taskRouteData[task];
476
+ if(!r){ fail('알 수 없는 task type: '+task); log('사용 가능: '+Object.keys(taskRouteData).join(', ')); process.exitCode=1; return; }
477
+ log('Task route: '+task);
478
+ log('\nRead before work:'); r.read.forEach(x=>log(' - .harness/'+x));
479
+ log('\nUpdate after work:'); r.update.forEach(x=>log(' - .harness/'+x));
480
+ log('\nPolicy: read AGENTS.md, context-routing.md, writeback-policy.md, then the files above. Do not store secrets in harness files.');
481
+ }
482
+
483
+ function help(){ log(['Leerness v'+VERSION,'','Usage:',' leerness init [path] [--yes] [--skills office,commerce-api|recommended|all]',' leerness migrate [path] [--dry-run]',' leerness status [path]',' leerness verify [path]',' leerness route <feature|ui|debugging|refactor|release|migration|new-install|skill-library|documentation>','','Skills:',' leerness skill list',' leerness skill add <name> [--path <project>]',' leerness skill remove <name> [--path <project>]',' leerness skill update <name> [--path <project>]',' leerness skill learn <name> --from <validated-skill-path> [--out <library-path>]','','Skill library lifecycle:',' leerness library guide [path]',' leerness library status <path>',' leerness library validate <path> [--strict-ai]',' leerness library verify <path> --ai --reviewer leerness-ai',' leerness library build <path> [--out ./dist] [--package leerness-skill-name]',' leerness library update <path> --from <validated-new-skill-path> [--version 1.3.0]',' leerness library merge <source-library> [--path <project>]',' leerness library migrate <path> [--version 1.0.0]',' leerness library publish <built-library> --target npm|git [--execute] [--repo https://github.com/gugu9999gu/leerness]',' leerness --version','','Examples:',' npx leerness init --skills recommended',' npx leerness skill learn coupang-order-sync --from .harness/skills/commerce-api/order-sync.md',' npx leerness library verify .harness/library/coupang-order-sync --ai --reviewer leerness-ai',' npx leerness library build .harness/library/coupang-order-sync',' npx leerness library publish .harness/library/coupang-order-sync/dist/coupang-order-sync --target npm --execute',''].join('\n')); }
484
+
485
+ async function main(){ const parsed=parseArgs(process.argv.slice(2)); const args=parsed.positionals; const flags=parsed.flags; if(flags.version||flags.v){ log(VERSION); return; } if(flags.help||flags.h){ help(); return; } const cmd=args[0]||'init'; if(cmd==='init') return init(args[1]||process.cwd(),flags); if(cmd==='migrate') return migrate(args[1]||process.cwd(),flags); if(cmd==='status') return status(args[1]||process.cwd()); if(cmd==='verify') return verify(args[1]||process.cwd()); if(cmd==='route') return routeCommand(args[1]||'list'); if(cmd==='skill') return skillCommand(args,flags); if(cmd==='library') return libraryCommand(args,flags); help(); process.exitCode=1; }
454
486
  main().catch(err=>{ fail(err.stack||err.message); process.exit(1); });
@@ -0,0 +1,29 @@
1
+ # AX Migration Guide for AI Agents
2
+
3
+ 구버전 하네스, 자체 AGENTS/CLAUDE 지침, 오래된 `.harness/` 파일을 Leerness 최신 구조로 옮기기 위한 AI 전용 가이드입니다.
4
+
5
+ ## 목표
6
+
7
+ 기존 지식을 잃지 않고, 새 구조에서 AI가 어떤 파일을 읽고 어떤 파일을 갱신해야 하는지 명확하게 만듭니다.
8
+
9
+ ## 절차
10
+
11
+ 1. `leerness migrate --dry-run`으로 감지 목록을 확인합니다.
12
+ 2. 기존 파일을 `.harness/archive/legacy-migration-*`에 백업합니다.
13
+ 3. legacy 내용을 새 목적지로 분류합니다.
14
+ 4. `context-routing.md`, `writeback-policy.md`, `task-type-map.md`를 생성합니다.
15
+ 5. `AGENTS.md`가 새 라우팅 파일들을 보도록 갱신합니다.
16
+ 6. 민감정보 값은 제거하고 변수명만 남깁니다.
17
+ 7. `leerness verify`를 실행합니다.
18
+ 8. `session-handoff.md`에 마이그레이션 결과와 다음 작업을 기록합니다.
19
+
20
+ ## Legacy mapping
21
+
22
+ | Legacy content | New destination |
23
+ |---|---|
24
+ | 프로젝트 목적/방향 | project-brief.md |
25
+ | 현재 상태/작업 이력 | current-state.md, task-log.md |
26
+ | 구조/모듈/데이터 흐름 | architecture.md, context-map.md |
27
+ | 기존 AI 규칙 | AGENTS.md, guardrails.md, context-routing.md |
28
+ | 배포 이슈 | release-checklist.md |
29
+ | 성공한 반복 작업 | skill candidate 또는 .harness/skills/ |