leerness 1.36.23 → 1.36.25
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 +17 -0
- package/README.md +8 -8
- package/bin/leerness.js +103 -76
- package/lib/catalogs.js +9 -9
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,22 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.36.25 — 2026-07-15 — 내장 스킬 9종 트리거 description + export/publish 합성 우선순위 — "언제 로드할지"를 알 수 있게 (obra/superpowers P0)
|
|
4
|
+
|
|
5
|
+
superpowers 검토(1.36.22)에서 이연한 P0. **결함(도그푸딩 실측)**: BUILTIN_CATALOG 9개 스킬 전부 `description` 0/9 → (1) 설치 스킬 리더가 capabilities 나열로 폴백("feature-contracts 작성, 재사용 우선 검사…" = 에이전트가 "지금 로드할까"를 판단할 수 없는 워크플로 요약), (2) `skill export`/`skill publish` 가 description 을 displayNameKo("기능 구현 표준 스킬")로 합성 — **좋은 description 이 있어도 우선순위가 displayNameKo 1순위라 무시**되는 구조였다.
|
|
6
|
+
|
|
7
|
+
- **BUILTIN_CATALOG 9/9 에 트리거 서술 description 신설** — superpowers 규율("description 은 트리거 조건 전용 — 워크플로 요약 금지") 적용: ko 트리거("~할 때 사용") + en 트리거절("Use when …"), 전부 40~200자(합성 시 `.slice(0,200)` 생존).
|
|
8
|
+
- **합성 우선순위 역전 3사이트** — `data.displayNameKo || data.description` → `data.description || data.displayNameKo` (export 1 + publish 계열 2). 실측: `skill export feature-implementation` 산출 SKILL.md frontmatter 가 "기능 구현 표준 스킬"(구) → "새 기능 구현을 시작할 때 사용 — … Use when starting to implement a new feature."(신). `skill list` 표시(displayNameKo)는 무변경.
|
|
9
|
+
- **검증**: selftest 295/295(9/9 존재 + 트리거 형태 + 슬라이스 생존 + displayNameKo 반복 아님 + 우선순위 역전 3사이트 — 자기참조 트랩은 split-literal 로 회피, 3번째 재발), export 실측, 게이트 e2e, 게시본 클린룸.
|
|
10
|
+
- 이연: `_lintSkillMeta` 순수 lint + `skill lint` CLI(P1/P2) — description 데이터가 먼저 채워져야 lint 가 의미 있음(이번에 충족). CJK 분기 본문 예산 포함해 다음 라운드 후보.
|
|
11
|
+
|
|
12
|
+
**하네스 문서 버전표기 제거 (사용자 지시, 동일 릴리스 합류)**: 설치되는 하네스 문서 템플릿(AGENTS/CLAUDE/session-workflow 등)의 지시문마다 붙어 있던 내부 버전표기(`(1.9.39+)`, `(1.9.8)`, `- 1.9.56+ …` 불릿 접두, `# 1.9.59+ —` 명령주석 등 **79건**)를 제거 — 사용자에게 무의미한 내부 이력 노이즈. 정보가 있는 괄호는 내용만 보존(`(1.9.78: 5신호+보안)`→`(5신호+보안)`), 사실 기록(migration-report `Version:`, task-log "vX initialized", 라운드 범위 데이터)은 유지. 저장소 자체 CLAUDE.md/AGENTS.md 지시 라인도 동일 정리(이력 섹션 `### 1.9.207 —` 은 역사 기록이라 불변). **실증**: fresh `init` 산출물 전수 스캔 — 지시문 버전표기 잔존 0(사실 기록 3건만).
|
|
13
|
+
|
|
14
|
+
## 1.36.24 — 2026-07-14 — requests 계열 positional 경로 인식 — 다른 프로젝트에 조용히 오기록되던 갭 (UR-0027 확장, 실피해 재현)
|
|
15
|
+
|
|
16
|
+
- **결함(실피해 재현)**: `requests` 계열만 positional 경로를 지원하지 않아 `requests add "text" C:/other/proj` 가 **경로 인자를 조용히 무시하고 cwd 프로젝트에 기록** 후 성공을 보고했다. `task`/`rule` 은 `_taskPositionalPath` 로 지원 → 표면 간 불일치가 실수를 유도(1.36.21 라운드에서 본인이 직접 당해 leerness-pkg 에 UR-0060 오기록·정리한 건).
|
|
17
|
+
- **수정(배선 1줄)**: rule 선례(`arg('--path', null) || _taskPositionalPath(args, 2) || process.cwd()`)와 동일 배선. 인프라는 이미 전부 존재 — `_taskPositionalPath` 는 선행 구분자(path-like)만 인정해 ID(`UR-0001`)/텍스트/내부 슬래시 제목(`src/auth …`)을 경로로 오인하지 않고, `requests add` 는 `_parseAddTitle`(1.9.416)이 텍스트를 path-like 에서 끊어 텍스트/경로 분리도 기존과 동일. UR-0027 이 경고한 "존재 디렉토리 인식"(bare 이름) 은 도입하지 않음 — FP 없는 기존 계약 유지.
|
|
18
|
+
- **검증**: selftest 294/294(배선 소스가드 + 순수 행위 3종: 절대경로 인정/ID 미오인/내부슬래시 미오인). 실측 — 피해 케이스 재현: cwd=내 프로젝트에서 `requests add "…" <다른경로>` → **대상 프로젝트에 기록 + 내 프로젝트 바이트 불변**, list/drop positional 동작, `--path` 우선 유지, path-only 빈 텍스트 거부(exit 1) 무회귀. 게이트 e2e, 게시본 클린룸.
|
|
19
|
+
|
|
3
20
|
## 1.36.23 — 2026-07-14 — memory search: 한국어↔영어 동의어(핸드오프 0→38) + BM25 랭킹("앞 N건"→"상위 N건") + JSON 정합
|
|
4
21
|
|
|
5
22
|
ui-ux-pro-max 의 BM25 검색엔진을 검토해 **정렬 레이어로만** 이식. 원안(BM25 를 리콜 엔진으로)은 부적합 — **토큰화 리콜은 언어별 형태론 가정을 끌어들여** 기존 히트를 잃는다. 실측: `memory search "핸드오프"` 는 substring 이라 "핸드오프**를** 자동화…"를 찾지만, 공백 토큰화 BM25 로 리콜을 대체하면 doc 토큰이 `['핸드오프를',…]` 이라 쿼리와 불일치해 **지금 찾히는 문서가 0건**이 된다(교착어 조사가 대표 사례이고, 굴절·합성어 언어에서도 같은 계열의 손실). 형태소 분석기는 의존성 0 위반이라 불가 → substring 은 **언어 중립적이고 상위집합 안전**하므로 리콜로 유지한다.
|
package/README.md
CHANGED
|
@@ -121,7 +121,7 @@ MIT
|
|
|
121
121
|
<!-- leerness:project-readme:start -->
|
|
122
122
|
## Leerness Project Harness
|
|
123
123
|
|
|
124
|
-
이 프로젝트는 Leerness v1.36.
|
|
124
|
+
이 프로젝트는 Leerness v1.36.25 하네스를 사용합니다. AI 에이전트는 작업 전 `leerness handoff`로 컨텍스트를 적재하고, 작업 후 `leerness check`/`leerness audit`/`leerness session close`를 수행해야 합니다.
|
|
125
125
|
|
|
126
126
|
### 정체성 — AI 에이전트 운영 레이어 (UR-0030)
|
|
127
127
|
|
|
@@ -175,7 +175,7 @@ leerness memory restore decision <date|title>
|
|
|
175
175
|
|
|
176
176
|
### MCP server (외부 AI 통합)
|
|
177
177
|
|
|
178
|
-
Leerness v1.36.
|
|
178
|
+
Leerness v1.36.25는 stdio JSON-RPC MCP server를 내장합니다 — Claude Code · Cursor · Codex CLI 등 외부 AI에 **86개 도구**를 노출:
|
|
179
179
|
|
|
180
180
|
```jsonc
|
|
181
181
|
// 카테고리별
|
|
@@ -194,18 +194,18 @@ Leerness v1.36.23는 stdio JSON-RPC MCP server를 내장합니다 — Claude Cod
|
|
|
194
194
|
### Autonomous mode (자율 모드)
|
|
195
195
|
|
|
196
196
|
`<<autonomous-loop-dynamic>>` 신호만 보내면 AI가:
|
|
197
|
-
1) 다음 라운드 후보 선정 → 2) 코드 변경 → 3) stress-v* 신규 작성 + 누적 회귀 → 4) e2e 219/219 → 5) npm pack + git tag + GitHub release → 6) main 자동 push
|
|
197
|
+
1) 다음 라운드 후보 선정 → 2) 코드 변경 → 3) stress-v* 신규 작성 + 누적 회귀 → 4) e2e 219/219 → 5) npm pack + git tag + GitHub release → 6) main 자동 push → 7) session close → 8) 다음 라운드 예약.
|
|
198
198
|
|
|
199
|
-
현재 누적: **70 라운드 (1.9.40 → 1.36.
|
|
199
|
+
현재 누적: **70 라운드 (1.9.40 → 1.36.25)** · 매 라운드 GitHub release/태그 생성 · _reports/는 비공개 보존.
|
|
200
200
|
|
|
201
|
-
### 성능 가이드
|
|
201
|
+
### 성능 가이드
|
|
202
202
|
|
|
203
203
|
- `leerness handoff .` — 평균 ~1.5s (캐시 워밍업 후 ~0.6s)
|
|
204
204
|
- `leerness memory status --json` — 평균 ~250ms
|
|
205
205
|
- `leerness task list --json` — 평균 ~200ms
|
|
206
206
|
- `leerness drift check --json` — 평균 ~400ms
|
|
207
207
|
- MCP `tools/list` 응답 — 평균 ~150ms
|
|
208
|
-
- usage-stats / lessons / listAllSkills 모두 메모리 캐싱
|
|
208
|
+
- usage-stats / lessons / listAllSkills 모두 메모리 캐싱
|
|
209
209
|
|
|
210
210
|
### 빠른 시작
|
|
211
211
|
|
|
@@ -222,7 +222,7 @@ leerness handoff . # 컨텍스트 자동 로드
|
|
|
222
222
|
# 4. 세션 종료 시
|
|
223
223
|
leerness session close . # 9 카테고리 + 룰 검증 + 다음 라운드 추천
|
|
224
224
|
|
|
225
|
-
# 5. release 자동화 (
|
|
225
|
+
# 5. release 자동화 (main 자동 push 포함)
|
|
226
226
|
leerness release pack --close --auto-main-push
|
|
227
227
|
```
|
|
228
228
|
|
|
@@ -234,6 +234,6 @@ leerness release pack --close --auto-main-push
|
|
|
234
234
|
- `.harness/session-handoff.md`: 다음 세션 인수인계 (자동 작성)
|
|
235
235
|
- `.harness/lessons.md` / `decisions.md` / `rules.md`: 영구 메모리 (5 surface)
|
|
236
236
|
|
|
237
|
-
Last synced by Leerness v1.36.
|
|
237
|
+
Last synced by Leerness v1.36.25: 2026-07-15
|
|
238
238
|
<!-- leerness:project-readme:end -->
|
|
239
239
|
|
package/bin/leerness.js
CHANGED
|
@@ -34,7 +34,7 @@ const { CAPABILITY_SURFACE, POWERFUL_COMMANDS, ADAPTERS, REUSE_CATEGORIES, REUSE
|
|
|
34
34
|
const { tokenizeForRank: _tokenizeForRank, expandQuery: _expandQuery, scoreHits: _scoreHits, suggestTerms: _suggestTerms } = require('../lib/search-core'); // 1.36.23: memory search 랭킹 코어(순수·0-deps)
|
|
35
35
|
const { findCorruptedStateJson: _findCorruptedStateJson } = require('../lib/state-integrity'); // 1.36.1 (클린룸 리뷰 FN): .harness/*.json 상태 무결성 (audit/health/check 공유)
|
|
36
36
|
|
|
37
|
-
const VERSION = '1.36.
|
|
37
|
+
const VERSION = '1.36.25';
|
|
38
38
|
|
|
39
39
|
// 1.9.290 (UR-0037, Codex gpt-5.5 #4 수렴): CLI 전용 부작용은 require 시 실행하지 않는다.
|
|
40
40
|
// 이전: warning listener 제거 / NODE_OPTIONS 변경 / chcp IIFE 가 top-level 즉시 실행 → require('harness') 시 호스트 프로세스 오염.
|
|
@@ -366,18 +366,18 @@ function managedReadmeBlock(project) {
|
|
|
366
366
|
'### Autonomous mode (자율 모드)',
|
|
367
367
|
'',
|
|
368
368
|
'`<<autonomous-loop-dynamic>>` 신호만 보내면 AI가:',
|
|
369
|
-
'1) 다음 라운드 후보 선정 → 2) 코드 변경 → 3) stress-v* 신규 작성 + 누적 회귀 → 4) e2e 219/219 → 5) npm pack + git tag + GitHub release → 6) main 자동 push
|
|
369
|
+
'1) 다음 라운드 후보 선정 → 2) 코드 변경 → 3) stress-v* 신규 작성 + 누적 회귀 → 4) e2e 219/219 → 5) npm pack + git tag + GitHub release → 6) main 자동 push → 7) session close → 8) 다음 라운드 예약.',
|
|
370
370
|
'',
|
|
371
371
|
`현재 누적: **70 라운드 (1.9.40 → ${VERSION})** · 매 라운드 GitHub release/태그 생성 · _reports/는 비공개 보존.`,
|
|
372
372
|
'',
|
|
373
|
-
'### 성능 가이드
|
|
373
|
+
'### 성능 가이드',
|
|
374
374
|
'',
|
|
375
375
|
'- `leerness handoff .` — 평균 ~1.5s (캐시 워밍업 후 ~0.6s)',
|
|
376
376
|
'- `leerness memory status --json` — 평균 ~250ms',
|
|
377
377
|
'- `leerness task list --json` — 평균 ~200ms',
|
|
378
378
|
'- `leerness drift check --json` — 평균 ~400ms',
|
|
379
379
|
'- MCP `tools/list` 응답 — 평균 ~150ms',
|
|
380
|
-
'- usage-stats / lessons / listAllSkills 모두 메모리 캐싱
|
|
380
|
+
'- usage-stats / lessons / listAllSkills 모두 메모리 캐싱',
|
|
381
381
|
'',
|
|
382
382
|
'### 빠른 시작',
|
|
383
383
|
'',
|
|
@@ -394,7 +394,7 @@ function managedReadmeBlock(project) {
|
|
|
394
394
|
'# 4. 세션 종료 시',
|
|
395
395
|
'leerness session close . # 9 카테고리 + 룰 검증 + 다음 라운드 추천',
|
|
396
396
|
'',
|
|
397
|
-
'# 5. release 자동화 (
|
|
397
|
+
'# 5. release 자동화 (main 자동 push 포함)',
|
|
398
398
|
'leerness release pack --close --auto-main-push',
|
|
399
399
|
'```',
|
|
400
400
|
'',
|
|
@@ -428,8 +428,8 @@ function coreFiles(root, lang = 'ko', selectedSkills = [], opts = {}) {
|
|
|
428
428
|
const project = detectProjectName(root);
|
|
429
429
|
const skillRows = Object.entries(skillCatalog).map(([k, v]) => `| ${k} | ${v.displayNameKo} | ${v.capabilities.join(', ')} | ${v.lastUpdated} | ${v.verification} |`).join('\n');
|
|
430
430
|
const _files = {
|
|
431
|
-
'AGENTS.md': `${MARK}\n# Leerness Agent Instructions\n\n## ⭐ 매 세션 첫
|
|
432
|
-
'CLAUDE.md': `${MARK}\n# Claude Code Instructions\n\nFollow AGENTS.md. Always run \`leerness handoff .\` at the start and \`leerness session close .\` before ending a session.\n\n**⭐ 매 세션 첫
|
|
431
|
+
'AGENTS.md': `${MARK}\n# Leerness Agent Instructions\n\n## ⭐ 매 세션 첫 행동\n**반드시 \`.harness/session-workflow.md\`를 먼저 읽고 6단계 워크플로를 따른다**: 요청분석→계획→분배→sub-agent작업→종합검증→마감. 라운드 길이/복잡도 무관, drift 방지를 위해 모든 작업에 동일 흐름 유지.\n\n## 정적 vs 동적 — leerness 역할 경계\n**AGENTS.md = 정적 프로젝트 지침** (코딩 규칙·테스트 명령·금지 사항·배포 절차 — 자주 안 변함).\n**leerness = 동적 작업 상태·기억·검증·인수인계** (현재 목표·수정 파일·실패 시도·검증 결과·다음 에이전트 인계 — 매 작업 변함).\n- 규칙/명령/금지는 여기 AGENTS.md 에 적는다.\n- 동적 상태(결정/교훈/계획/진행/검증/인수인계)는 leerness 가 **기본 워크스페이스 \`.harness/\`** 에 기록한다 (decisions.md / lessons.md / plan.md / progress-tracker.md / session-handoff.md). \`leerness handoff\` · \`decision add\` · \`lesson save\` 등이 여기에 쓴다.\n- (선택) \`leerness state show|start|record|verify|handoff\` (또는 MCP \`leerness_state_*\`) 의 JSON 상태 substrate 는 \`.leerness/\` (에이전트 간 인수인계 표준 — state 명령 사용 시 생성). 메인 워크스페이스(.harness)와 별개.\n- leerness 는 AGENTS.md 를 **대체하지 않고 보완**한다. 정적 지침은 여기, 동적 상태는 leerness.\n\n## Mandatory read order (session start)\n1. **.harness/session-workflow.md** (6단계 워크플로 — 최우선)\n2. .harness/context-routing.md\n3. .harness/session-handoff.md\n4. .harness/current-state.md\n5. .harness/plan.md\n6. .harness/progress-tracker.md\n7. .harness/guideline.md\n8. .harness/protected-files.md\n9. .harness/writeback-policy.md\n10. .harness/anti-lazy-work-policy.md\n11. **.harness/rules.md** (사용자 정의 영구 룰 — 매 세션 반드시 따름)\n\n## Required behavior\n- 작업 시작 시 \`leerness handoff .\`를 실행해 컨텍스트를 적재합니다 (handoff가 active rules를 자동 출력).\n- 작업 분류는 \`leerness route <task-type>\`로 확인합니다 (planning, feature, bugfix, refactor, research, consistency, release, migration, session-start, session-close, harness-maintenance).\n- 보호 파일/관리 섹션을 삭제하지 않습니다. 머지·아카이브·deprecated 표시를 사용합니다.\n- 의미 있는 변경 후 progress-tracker, current-state, task-log, session-handoff를 갱신합니다.\n- 완료 선언 전 \`leerness check .\` 또는 \`leerness lazy detect .\`로 자기검증하고, \`leerness lens\`의 분야별 자기질문에 답합니다 (코드: "선임 개발자가 복잡하다고 느끼지 않을까?" / 디자인: "선임 디자이너와 일반 사용자가 이쁘고 직관적이라 느낄까?").\n- 변경 전 secret/encoding 가드: \`leerness scan secrets .\`, \`leerness encoding check .\`.\n- 같은 기능 중복 생성 전 design-system.md, consistency-policy.md, reuse-map.md를 확인합니다.\n- 매 세션 종료 시 \`leerness session close .\`로 9개 카테고리(완료/진행중/미완료/예정/대기/보류/차단/드랍/검증) + **활성 룰 검증 결과**를 보고합니다.\n- 업데이트는 \`leerness update --check\` (감지) → \`leerness update --yes\` (자동 마이그레이션).\n\n## 자연어 회고/통찰/브레인스토밍\n사용자가 자연어로 회고/통찰/브레인스토밍을 요청하면 즉시 leerness 명령으로 호출합니다.\n\n| 사용자 발화 (자연어) | 즉시 실행할 명령 |\n|---|---|\n| "회고해줘 / 돌아보자 / 정리해줘" | \`leerness retro\` |\n| "최근 N일 회고" | \`leerness retro --days N\` |\n| "통계 / 누적 지표 / insights" | \`leerness insights\` |\n| "X에 대해 브레인스토밍 / X 관련 자료 / X 시작 전 검토" | \`leerness brainstorm "X"\` |\n\nsession close가 매번 자동으로 한 줄 요약을 출력하고, 5세션마다 자동 깊은 회고를 실행합니다. 사용자가 명시 요청 시 즉시 호출.\n\n## 자연어 룰 처리\n사용자가 자연어로 영구 룰을 요청하면 즉시 leerness rule 명령으로 등록합니다.\n\n| 사용자 발화 (자연어) | 즉시 실행할 명령 |\n|---|---|\n| "매 업데이트마다 버전 bump해줘" | \`leerness rule add "버전을 patch로 bump" --trigger every-update\` |\n| "매 커밋마다 패치노트 추가해줘" | \`leerness rule add "패치노트 추가" --trigger every-commit\` |\n| "세션 종료마다 배포해줘" | \`leerness rule add "배포 (release publish)" --trigger session-close\` |\n| "X 룰 중지/그만/끄기" | \`leerness rule pause <ID>\` (해당 룰 ID는 list로 확인) |\n| "X 룰 제거/삭제" | \`leerness rule remove <ID>\` |\n| "모든 룰 중지" | \`leerness rule stop\` |\n| "룰 다시 켜줘" | \`leerness rule resume-all\` 또는 \`leerness rule resume <ID>\` |\n\n룰을 등록한 후 사용자에게 등록 결과(ID + trigger + 설명)를 보고하고, 그 이후 매 세션마다 자동 적용합니다. 사용자가 "중지" 또는 "제거"를 명시적으로 말하기 전까지는 룰을 비활성화하지 않습니다.\n\n## 룰 자동 적용\nleerness가 자동 검증 가능한 trigger:\n- **every-update / version bump 키워드 룰**: package.json의 version이 갱신됐는지 검사 (handoff/session close가 baseline 캐시와 비교).\n- **CHANGELOG / 패치노트 키워드 룰**: CHANGELOG.md의 mtime이 갱신됐는지 검사.\n- **test / 테스트 / verify 키워드 룰**: review-evidence.md에 오늘 verify-code 흔적이 있는지 검사.\n- **배포 / publish / push 키워드 룰**: 자동 검증 불가 → 사용자에게 release publish 명령을 안내.\n\n자동 검증 가능한 룰의 실행은 \`leerness release bump\`, \`leerness release note "..."\`, \`leerness release publish\`를 사용해 자동화합니다.\n`,
|
|
432
|
+
'CLAUDE.md': `${MARK}\n# Claude Code Instructions\n\nFollow AGENTS.md. Always run \`leerness handoff .\` at the start and \`leerness session close .\` before ending a session.\n\n**⭐ 매 세션 첫 행동**: \`.harness/session-workflow.md\`의 6단계 워크플로(요청분석→계획→분배→sub-agent→종합검증→마감)를 따라야 함. drift critical 시 \`leerness drift check --auto-fix\`로 자동 회복.\n\nProtected files must not be deleted. Read .harness/anti-lazy-work-policy.md before claiming completion.\n\n## 자연어 영구 룰\n사용자가 "매 X마다 Y를 해줘" 같은 자연어 룰을 말하면 즉시 \`leerness rule add "Y" --trigger every-X\`로 등록하세요. 등록된 룰은 매 세션 \`handoff\`가 자동 출력하고, \`session close\`가 자동 검증해 보고합니다. 사용자가 "중지" / "그만" / "끄기"를 명시할 때만 \`rule pause/remove\`를 호출합니다.\n\n자세한 매핑은 AGENTS.md의 "자연어 룰 처리" 표를 참고하세요.\n`,
|
|
433
433
|
'.cursor/rules/leerness.mdc': `${MARK}\n---\nalwaysApply: true\n---\nFollow AGENTS.md and .harness/context-routing.md.\nRun: \`leerness handoff .\` at session start.\nRun: \`leerness session close .\` at session end.\nPreserve Leerness protected files.\n`,
|
|
434
434
|
'.github/copilot-instructions.md': `${MARK}\n# Copilot Instructions\n\nUse AGENTS.md and .harness/ as project memory.\nDo not remove protected Leerness files.\nBefore completion, ensure plan.md, progress-tracker.md, current-state.md, session-handoff.md are updated.\n`,
|
|
435
435
|
'.harness/HARNESS_VERSION': VERSION + '\n',
|
|
@@ -456,7 +456,7 @@ function coreFiles(root, lang = 'ko', selectedSkills = [], opts = {}) {
|
|
|
456
456
|
'.harness/reuse-map.md': fm('reuse-map', ['새 컴포넌트/API/helper 생성 전','중복 기능 감지'], ['재사용 가능한 요소 추가'], `# Reuse Map\n\n| Capability | Existing Element | Reuse Method | Notes |\n|---|---|---|---|\n`),
|
|
457
457
|
'.harness/feature-contracts.md': fm('feature-contracts', ['기능 구현/수정 전'], ['기능 입출력/상태/오류 변경'], `# Feature Contracts\n\n## Template\n- Feature:\n- Input:\n- Output:\n- States:\n- Errors:\n- Related files:\n- Test evidence ID:\n`),
|
|
458
458
|
// 1.9.141: Feature Causality Graph — 신규 기능/형식 변경 시 영향 범위 자동 추적 (사용자 요청)
|
|
459
|
-
'.harness/feature-graph.md': fm('feature-graph', ['신규 기능 추가 전','데이터 형식 변경 전','외부 API 매칭 작업 전'], ['feature 등록 / 링크 / impact 회수'], `# Feature Graph
|
|
459
|
+
'.harness/feature-graph.md': fm('feature-graph', ['신규 기능 추가 전','데이터 형식 변경 전','외부 API 매칭 작업 전'], ['feature 등록 / 링크 / impact 회수'], `# Feature Graph\n\n> **목적**: 각 기능의 인과관계를 정확히 정리해서 코드 작성 전 영향 범위를 자동 추적.\n> 신규 기능 추가, 데이터 형식 변경, 외부 API 매칭 작업 전 \`leerness feature impact <id>\`로 확인.\n> handoff가 현재 task 키워드로 자동 매칭해서 영향받는 feature 목록을 회수.\n\n## How to use\n\n\`\`\`bash\nleerness feature add "User Auth" # F-0001 자동 부여\nleerness feature link F-0002 --depends-on F-0001 # 의존 관계\nleerness feature link F-0001 --affects F-0002,F-0005 # 영향 관계 (다수)\nleerness feature link F-0001 --co-changes-with F-0011 # 함께 변해야 하는 기능\nleerness feature impact F-0001 # 영향받는 전체 (transitive)\nleerness feature list --json # 그래프 JSON\nleerness feature show F-0001 # 단일 상세\n\`\`\`\n\n## Nodes\n\n`),
|
|
460
460
|
'.harness/testing-strategy.md': fm('testing-strategy', ['검증 전','릴리즈 전'], ['테스트 전략 변경'], `# Testing Strategy\n\n- Typecheck (\`tsc --noEmit\` 또는 동등)\n- Lint (\`npm run lint\` 등)\n- Unit/Integration/E2E\n- Manual smoke test\n- Browser/UI smoke (frontend 변경 시)\n\n## Evidence Format\nEach completed task must reference an evidence ID stored in .harness/review-evidence.md.\n`),
|
|
461
461
|
'.harness/review-checklist.md': fm('review-checklist', ['PR/리뷰 전'], ['리뷰 기준 변경'], `# Review Checklist\n\n- [ ] 계획과 정렬되어 있는가\n- [ ] progress-tracker가 갱신되었는가\n- [ ] 보호 파일을 삭제하지 않았는가\n- [ ] 디자인/기능 재사용을 확인했는가\n- [ ] 시크릿이 코드에 들어가지 않았는가 (\`leerness scan secrets\`)\n- [ ] 한글 인코딩 OK (\`leerness encoding check\`)\n- [ ] 게으름 평가 통과 (\`leerness lazy detect\`)\n`),
|
|
462
462
|
'.harness/release-checklist.md': fm('release-checklist', ['배포 전'], ['배포 조건/환경변수/롤백 변경'], `# Release Checklist\n\n- [ ] \`leerness verify .\`\n- [ ] \`leerness audit .\`\n- [ ] \`leerness scan secrets .\`\n- [ ] \`leerness encoding check .\`\n- [ ] 프로젝트 typecheck/lint/test\n- [ ] 환경변수 (.env.example) 동기화\n- [ ] 롤백 방법 확인\n- [ ] CHANGELOG 갱신\n`),
|
|
@@ -488,7 +488,7 @@ leerness agents dispatch "<task>" --to <id> # 작업 유형 추천 자동
|
|
|
488
488
|
- 작업 유형별 최적 sub-agent:
|
|
489
489
|
- 텍스트/번역/분석 → claude (1.7× 빠름)
|
|
490
490
|
- 깊은 코드 추론 → codex (가장 상세)
|
|
491
|
-
- 파일 직접 수정 → agy --yolo (정확, Antigravity CLI
|
|
491
|
+
- 파일 직접 수정 → agy --yolo (정확, Antigravity CLI)
|
|
492
492
|
- 보안 리뷰 → \`leerness review --persona security\`
|
|
493
493
|
- **충돌 방지 규칙 (필수)**:
|
|
494
494
|
- 각 sub-agent에 *자신만 수정할 파일 경로* 명시
|
|
@@ -510,22 +510,22 @@ leerness review <file> --persona security,performance,ux
|
|
|
510
510
|
|
|
511
511
|
## Step 6. 세션 마감 + 인계 + 다음 라운드 추천
|
|
512
512
|
\`\`\`bash
|
|
513
|
-
leerness session close . #
|
|
513
|
+
leerness session close . # --suggest default 활성 (마감 + 다음 라운드 자동)
|
|
514
514
|
leerness session close . --no-suggest # suggest 비활성 (이전 동작)
|
|
515
515
|
|
|
516
516
|
# 분리 호출도 가능:
|
|
517
|
-
leerness skill suggest . #
|
|
517
|
+
leerness skill suggest . # 반복 패턴 → 새 skill 후보
|
|
518
518
|
leerness drift check . # 4 신호 + 4 레벨 점검
|
|
519
519
|
leerness audit . --fix # 누락 메타 자동 보강
|
|
520
520
|
\`\`\`
|
|
521
521
|
|
|
522
|
-
## 🧠 Memory CRUD Quick Reference
|
|
522
|
+
## 🧠 Memory CRUD Quick Reference
|
|
523
523
|
|
|
524
524
|
5 Memory Surface 모두 CRUD CLI + MCP 노출 완성:
|
|
525
525
|
|
|
526
526
|
| Surface | CREATE | READ | DELETE | RESTORE |
|
|
527
527
|
|---|---|---|---|---|
|
|
528
|
-
| **tasks** | task add | task list --json
|
|
528
|
+
| **tasks** | task add | task list --json | task drop | task update |
|
|
529
529
|
| **decisions** | decision add | decision list --json | decision drop | memory restore decisions |
|
|
530
530
|
| **lessons** | lesson save | lesson list [--tag] | lesson drop | memory restore lessons |
|
|
531
531
|
| **plan** | plan add | plan list --json | plan remove | memory restore plan |
|
|
@@ -534,69 +534,69 @@ leerness audit . --fix # 누락 메타 자동 보강
|
|
|
534
534
|
\`\`\`bash
|
|
535
535
|
leerness memory status [--json] # 5종 상태 통합 조회 (T/D/R/P/L 카운트)
|
|
536
536
|
leerness memory archive list [--surface s] # DELETE archive 통합 조회 (복원 후보)
|
|
537
|
-
leerness memory restore <surface> <target> # archive → active 복귀 (DELETE→RESTORE cycle
|
|
537
|
+
leerness memory restore <surface> <target> # archive → active 복귀 (DELETE→RESTORE cycle)
|
|
538
538
|
\`\`\`
|
|
539
539
|
|
|
540
540
|
**잘못 저장한 항목 복구**:
|
|
541
541
|
1. \`memory archive list\` — 복원 후보 확인
|
|
542
542
|
2. \`memory restore decisions "PostgreSQL"\` — archive → active
|
|
543
|
-
3. handoff 가 매 세션 자동으로 24h 내 archive 활동 알림
|
|
543
|
+
3. handoff 가 매 세션 자동으로 24h 내 archive 활동 알림
|
|
544
544
|
|
|
545
545
|
|
|
546
546
|
- session close가 누락되면 다음 세션 시작 시 drift critical 발생.
|
|
547
547
|
- 자동 회복 옵션: \`drift check --auto-fix\` (critical 시 session close 자동 실행).
|
|
548
|
-
-
|
|
549
|
-
-
|
|
550
|
-
-
|
|
551
|
-
-
|
|
552
|
-
-
|
|
553
|
-
-
|
|
554
|
-
-
|
|
555
|
-
-
|
|
556
|
-
-
|
|
557
|
-
-
|
|
558
|
-
-
|
|
559
|
-
-
|
|
560
|
-
-
|
|
561
|
-
-
|
|
562
|
-
-
|
|
563
|
-
-
|
|
564
|
-
-
|
|
565
|
-
-
|
|
566
|
-
-
|
|
567
|
-
-
|
|
568
|
-
-
|
|
569
|
-
-
|
|
570
|
-
-
|
|
571
|
-
-
|
|
572
|
-
-
|
|
573
|
-
-
|
|
574
|
-
-
|
|
575
|
-
-
|
|
576
|
-
-
|
|
577
|
-
-
|
|
578
|
-
-
|
|
579
|
-
-
|
|
580
|
-
-
|
|
581
|
-
-
|
|
582
|
-
-
|
|
583
|
-
-
|
|
584
|
-
-
|
|
585
|
-
-
|
|
586
|
-
-
|
|
587
|
-
-
|
|
588
|
-
-
|
|
589
|
-
-
|
|
590
|
-
-
|
|
591
|
-
-
|
|
592
|
-
-
|
|
593
|
-
-
|
|
594
|
-
-
|
|
595
|
-
-
|
|
596
|
-
-
|
|
597
|
-
-
|
|
598
|
-
-
|
|
599
|
-
-
|
|
548
|
+
- handoff가 매 세션 시작 시 **과거 lessons 자동 재상기** (현재 task 키워드 기준).
|
|
549
|
+
- handoff가 현재 task와 매칭되는 **설치된 skill을 자동 추천** (jaccard 기반, default ON, \`--no-skill-suggest\`로 끄기).
|
|
550
|
+
- lessons 인덱스에 \`task-log.md\` 실패 라인까지 포함 → 회수 범위 확장.
|
|
551
|
+
- handoff가 \`skill-suggestions.md\` rolling history (과거 같은 키워드 매칭 결과)도 자동 노출.
|
|
552
|
+
- handoff에 보안 요약 1~2 line 자동 (\`.env\` ↔ \`.env.example\` 동기화 + \`.gitignore\` 시크릿 누락).
|
|
553
|
+
- \`.env\` 가 \`.gitignore\` 에 누락 시 🚨 CRITICAL + \`LEERNESS_AUTO_SECURITY_FIX=1\` 환경변수 시 \`audit --fix\` 자동 실행.
|
|
554
|
+
- handoff Date/Project 직후 통합 헤드라인 한 줄 (drift / 보안 / MCP / skill query / 설치 skill 수).
|
|
555
|
+
- \`leerness health\` 한 줄로 종합 점검 (drift + 보안 + skills + usage + tasks).
|
|
556
|
+
- \`leerness drift check --auto-fix\` 가 보안 신호 발견 시 \`audit --fix\` 자동 실행 → 재검사.
|
|
557
|
+
- MCP server **18 도구** (handoff/drift/audit/verify_claim/contract/agents/reuse/whats_new/usage_stats/session_close/skill_suggest/lessons/task_export/env_check/brainstorm/skill_match/skill_list/health).
|
|
558
|
+
- MCP server **21 도구** (skill_search/skill_info/benchmark 추가).
|
|
559
|
+
- \`leerness handoff --json\` (외부 AI/MCP 통합용 구조화 출력).
|
|
560
|
+
- \`leerness skill publish\` 보안 사전 점검 통합 (health 통과 후 publish).
|
|
561
|
+
- \`leerness handoff --quiet\` (자동화/CI 모드 — 자동 회수 라인 비활성).
|
|
562
|
+
- 🏆 마일스톤 — 30 라운드 자율 누적, stress-v45 30/30 PASS, e2e 219/219 PASS.
|
|
563
|
+
- \`leerness lazy detect --json\` + MCP **22 도구** (\`leerness_lazy_detect\` 추가 — 거짓 완료/empty handoff/no test run/TODO 미추적 신호 JSON).
|
|
564
|
+
- \`leerness audit --json\` 구조화 출력 (findings 11종 kind: design_dup/design_system_default/reuse_map_empty/milestone_unlinked/handoff_not_generated/current_state_stale/readme_version_mismatch/npm_cve/gitignore_missing_secrets/env_keys_missing/strict_promoted). MCP \`leerness_audit\`도 JSON 자동.
|
|
565
|
+
- \`leerness session close --json\` 마감 통계 JSON (taskCounts/rules/skillCandidates/drift/topCommands/mcpStats/workspacePeers). MCP \`leerness_session_close\`도 JSON 자동.
|
|
566
|
+
- MCP **23 도구** (\`leerness_retro\` 추가 — 4세션 누적 회고 JSON 외부 AI 노출).
|
|
567
|
+
- MCP **24 도구** (\`leerness_task_add\` 추가 — 외부 AI 가 task 즉시 등록, 양방향 제어 완성).
|
|
568
|
+
- MCP **25 도구** (\`leerness_task_update\` 추가 — task 상태/evidence/nextAction 갱신, read+add+update 3종 surface 완성).
|
|
569
|
+
- MCP **26 도구** (\`leerness_task_drop\` 추가 — task 폐기, **task CRUD 완성**: read/add/update/drop).
|
|
570
|
+
- \`leerness decision add\` CLI + MCP **27 도구** (\`leerness_decision_add\` — decisions.md 영구화 + handoff lessons 회수와 통합).
|
|
571
|
+
- \`leerness rule list --json\` + MCP **29 도구** (\`leerness_rule_add\` + \`leerness_rule_list\` — 자연어 영구 룰 R/W).
|
|
572
|
+
- MCP **30 도구 🎉 30 도구 마일스톤** (\`leerness_plan_add\` — plan.md milestone + progress-tracker 자동 동기화).
|
|
573
|
+
- MCP **31 도구** (\`leerness_lesson_save\` — lessons.md 직접 write, **Memory Write Surface 5종 완성**: tasks/decisions/rules/plan/lessons).
|
|
574
|
+
- handoff 통합 헤드라인에 **🧠 mem T/D/R/P/L 카운트** 추가 — 5종 메모리 영구화 상태 한눈에 확인.
|
|
575
|
+
- \`leerness memory status [--json]\` + MCP **32 도구** (\`leerness_memory_status\`) — 상세 상태 + 최근 항목 조회.
|
|
576
|
+
- \`leerness handoff --json\` 응답에 **\`memorySurface\` 필드 통합** — 단일 호출로 컨텍스트 + 5종 메모리 상태 동시 회수.
|
|
577
|
+
- \`leerness brainstorm\` 회수 범위에 **lessons.md + plan.md** milestone 추가 — Memory Surface 5종 완전 통합.
|
|
578
|
+
- \`leerness lesson list [--tag] [--json]\` + MCP **33 도구** (\`leerness_lesson_list\`) — lessons.md 전용 조회 + tag 필터.
|
|
579
|
+
- \`leerness decision list [--json]\` + MCP **34 도구** (\`leerness_decision_list\`) — decisions.md 전체 조회 (Decision/Reason/Alternatives/Impact 메타).
|
|
580
|
+
- \`leerness plan list [--json]\` + MCP **35 도구** (\`leerness_plan_list\`) — plan.md milestone 전체 (Status/Progress/Tasks). **Memory Surface READ 5종 완전 완성**.
|
|
581
|
+
- handoff 6번째 자동 회수 \`🆕 최근 24h 메모리 변동\` — 5종 surface 의 24h 내 추가 항목 자동 노출.
|
|
582
|
+
- \`session close --json\` 응답에도 \`memorySurface\` 필드 통합 — 마감 시 5종 메모리 상태 동시 회수.
|
|
583
|
+
- \`health --json\` 응답에도 \`memorySurface\` 필드 통합 — handoff/session close/memory status 모든 JSON 명령 일관성.
|
|
584
|
+
- \`leerness lesson drop <target>\` + MCP **36 도구** (\`leerness_lesson_drop\`) — 잘못 저장한 lesson 제거 (archive 자동 보존).
|
|
585
|
+
- \`leerness decision drop <target>\` + MCP **37 도구** (\`leerness_decision_drop\`) — 잘못 저장한 결정 제거 (archive 보존).
|
|
586
|
+
- \`leerness plan remove <M-XXXX|title>\` + MCP **38 도구** (\`leerness_plan_remove\`) — milestone 영구 제거 (archive 보존). **Memory Surface DELETE 5종 완전 완성** 🎉.
|
|
587
|
+
- \`leerness memory archive list [--surface decisions|lessons|plan] [--json]\` + MCP **39 도구** (\`leerness_memory_archive_list\`) — DELETE 5종 archive 통합 조회 (복원 후보 회수).
|
|
588
|
+
- \`leerness memory restore <surface> <target>\` + MCP **40 도구 🎉** (\`leerness_memory_restore\`) — archive → active 복귀 (DELETE→RESTORE cycle 완성). **MCP 40 도구 마일스톤**.
|
|
589
|
+
- handoff **7번째 자동 회수** — \`🗑 최근 24h archive\` (D/L/P 카운트 + 복원 후보 안내). DELETE 활동 자동 인지.
|
|
590
|
+
- 🎉 **60 라운드 자율 모드 마일스톤** — JSON 4종 (handoff/memory status/session close/health) \`memorySurface.archive\` 필드 통합. MCP 40 / handoff auto-recovery 7 / DELETE-RESTORE cycle 완성.
|
|
591
|
+
- \`brainstorm\` 회수 범위에 3 archive 파일 (decisions/lessons/plan archive) 통합 — 과거 제거된 ideas 가 새 brainstorm 시 다시 후보로 노출. \`hits.archive\` 필드 + 복원 안내 라인.
|
|
592
|
+
- \`session close\` 텍스트 모드에 archive 누적 라인 추가 — 마감 시점 DELETE 활동 가시화 (handoff 7번째 회수와 symmetric). archive 가시성 6 surface 완성.
|
|
593
|
+
- \`brainstorm\` 텍스트 모드 lessonsExplicit / planMilestones display 추가 — 데이터 수집은 됐지만 display 가 누락돼 있던 gap 보완 fix.
|
|
594
|
+
- \`leerness task list --json\` + MCP **41 도구** (\`leerness_task_list\`) — progress-tracker.md task 전체 JSON 조회 + \`--status\` 필터. Task surface CRUD MCP 완전 완성 (add/list/update/drop).
|
|
595
|
+
- MCP **42 도구** (\`leerness_rule_remove\`) — rules.md 에서 특정 rule 제거 + archive 보존. **5 surface CRUD MCP 완전 완성** (task/decision/lesson/plan/rule 모두 add/list/delete MCP 노출).
|
|
596
|
+
- MCP \`leerness_drift_check\` JSON 응답 fix — \`--json\` 플래그 자동 추가하여 외부 AI가 구조화된 drift 신호 회수 (score, level, signals[], healthy).
|
|
597
|
+
- \`.harness/session-workflow.md\` 템플릿에 **🧠 Memory CRUD Quick Reference** 섹션 추가 — 5 surface × CRUD 매트릭스 + archive cycle 워크플로 가이드. 신규 \`init\` 워크스페이스 즉시 적용.
|
|
598
|
+
- \`leerness memory archive list --query <keyword>\` + MCP \`leerness_memory_archive_list\` query 인자 — archive 항목 키워드 case-insensitive 검색 (target/originalHeader 매칭).
|
|
599
|
+
- \`leerness lesson list --query\` + \`leerness decision list --query\` + MCP 동일 인자 — active Memory 항목 키워드 검색 (lesson: text/tag, decision: title/decision/reason/alternatives/impact).
|
|
600
600
|
|
|
601
601
|
---
|
|
602
602
|
|
|
@@ -606,11 +606,11 @@ leerness memory restore <surface> <target> # archive → active 복귀 (DELETE
|
|
|
606
606
|
- [ ] plan/progress-tracker에 이번 라운드 task 등록됨 (또는 task sync)
|
|
607
607
|
- [ ] 모든 done 항목에 evidence 첨부됨 (verify-claim PASS)
|
|
608
608
|
- [ ] sub-agent 사용 시 contract verify PASS
|
|
609
|
-
- [ ] drift 점수 ≤ 30 (attention 이하) — \`leerness drift check\` (
|
|
609
|
+
- [ ] drift 점수 ≤ 30 (attention 이하) — \`leerness drift check\` (5신호 + 보안)
|
|
610
610
|
- [ ] session close 호출됨
|
|
611
|
-
- [ ]
|
|
612
|
-
- [ ]
|
|
613
|
-
- [ ]
|
|
611
|
+
- [ ] \`leerness health\`로 종합 점검 — drift + 보안 + skill + MCP + tasks
|
|
612
|
+
- [ ] \`.env\` 사용 중이면 \`.gitignore\` 시크릿 패턴 OK + \`.env.example\` 동기화
|
|
613
|
+
- [ ] 보안 critical 시 \`LEERNESS_AUTO_SECURITY_FIX=1\` 또는 \`audit --fix\`로 자동 회복
|
|
614
614
|
|
|
615
615
|
## Anti-pattern (drift 신호)
|
|
616
616
|
|
|
@@ -620,7 +620,7 @@ leerness memory restore <surface> <target> # archive → active 복귀 (DELETE
|
|
|
620
620
|
- ⚠ "테스트 돌렸으니 PASS" 자기 보고만 → verify-claim --run-tests 미실행
|
|
621
621
|
- ⚠ contract verify 생략 → 사양 불일치 BUG가 사용자에게 노출
|
|
622
622
|
`),
|
|
623
|
-
'.harness/anti-lazy-work-policy.md': fm('anti-lazy-work-policy', ['완료 선언 전'], ['게으른 작업 방지 기준 변경'], `# Anti Lazy Work Policy\n\n## Rules\n1. **증거 없는 완료 금지**: \"완료\"를 선언하려면 progress-tracker의 evidence 컬럼에 명령 출력/테스트 결과/스크린샷 경로 등이 있어야 합니다.\n2. **빈 핸드오프 금지**: 세션 종료 시 session-handoff.md의 Completed/In Progress/Next Exact Step이 모두 비어 있으면 close가 \"insufficient\" 상태로 표시됩니다.\n3. **부분 구현 자기보고**: 완전 구현이 아니면 status를 \`incomplete\`로, Next Exact Step에 \"무엇을 추가해야 끝나는지\" 한 줄을 적습니다.\n4. **검증 기록**: typecheck/lint/test 결과를 review-evidence.md에 누적 기록합니다.\n5. **TODO 표지**: 코드에 \`TODO\`/\`FIXME\`/\`XXX\`를 새로 도입하면 progress-tracker에 동일 ID로 추적합니다.\n6. **거짓 완료 자동 감지**: \`leerness lazy detect\`는 다음을 자동 점검합니다.\n - progress-tracker에 done인데 evidence가 비어있는 row\n - session-handoff의 Completed가 비어있고 Next Exact Step도 비어있음\n - 코드에 새 TODO/FIXME 추가 + progress-tracker에 추적 항목 없음\n - test 명령 실행 흔적 없음 (review-evidence.md 또는 task-log.md에 명령 기록)\n7. **품질 렌즈
|
|
623
|
+
'.harness/anti-lazy-work-policy.md': fm('anti-lazy-work-policy', ['완료 선언 전'], ['게으른 작업 방지 기준 변경'], `# Anti Lazy Work Policy\n\n## Rules\n1. **증거 없는 완료 금지**: \"완료\"를 선언하려면 progress-tracker의 evidence 컬럼에 명령 출력/테스트 결과/스크린샷 경로 등이 있어야 합니다.\n2. **빈 핸드오프 금지**: 세션 종료 시 session-handoff.md의 Completed/In Progress/Next Exact Step이 모두 비어 있으면 close가 \"insufficient\" 상태로 표시됩니다.\n3. **부분 구현 자기보고**: 완전 구현이 아니면 status를 \`incomplete\`로, Next Exact Step에 \"무엇을 추가해야 끝나는지\" 한 줄을 적습니다.\n4. **검증 기록**: typecheck/lint/test 결과를 review-evidence.md에 누적 기록합니다.\n5. **TODO 표지**: 코드에 \`TODO\`/\`FIXME\`/\`XXX\`를 새로 도입하면 progress-tracker에 동일 ID로 추적합니다.\n6. **거짓 완료 자동 감지**: \`leerness lazy detect\`는 다음을 자동 점검합니다.\n - progress-tracker에 done인데 evidence가 비어있는 row\n - session-handoff의 Completed가 비어있고 Next Exact Step도 비어있음\n - 코드에 새 TODO/FIXME 추가 + progress-tracker에 추적 항목 없음\n - test 명령 실행 흔적 없음 (review-evidence.md 또는 task-log.md에 명령 기록)\n7. **품질 렌즈 자가질문**: 완료 선언 전 \`leerness lens\`의 분야별 질문에 스스로 답합니다 — 코드: "선임 개발자가 이 코드를 보고 복잡하다고 느끼지 않을까?" / 디자인: "선임 디자이너와 일반 사용자가 봤을 때 이쁘고 편하고 직관적인가?". "그렇다(통과)"라고 답할 수 없으면 완료가 아닙니다. 분야를 바꾸면 인과관계로 연결된 분야(\`lens\` 출력의 ↔ 인과)의 질문도 다시 확인합니다.\n`),
|
|
624
624
|
'.harness/rules.md': _rulesHeader() + '\n',
|
|
625
625
|
'.harness/session-handoff.md': fm('session-handoff', ['세션 시작','다음 작업 이어받기'], ['세션 종료'], `# Session Handoff\n\nLast generated: (자동)\n\n## Completed\n-\n\n## In Progress\n-\n\n## Incomplete / Waiting / On Hold / Blocked\n-\n\n## Dropped\n-\n\n## Verification\n-\n\n## Recommended Direction\n-\n\n## Next Exact Step\n-\n`),
|
|
626
626
|
'.harness/leerness-maintenance.md': fm('leerness-maintenance', ['작업 시작','마이그레이션/릴리즈 전'], ['버전 정책 변경'], `# Leerness Maintenance\n\nAI agents should check:\n\n\`\`\`bash\nleerness --version\nleerness self check .\nleerness update --check # 24h 캐시 자동 감지\nleerness update --yes # 새 버전 발견 시 자동 마이그레이션\ncat .harness/HARNESS_VERSION\nnpm view leerness version\n\`\`\`\n`),
|
|
@@ -2983,6 +2983,30 @@ function _selfTestCases() {
|
|
|
2983
2983
|
const encOk = s.includes("(result.applied || []).some(a => a.action === 'failed')) process.exitCode = 1"); // encoding: 실패 exit1
|
|
2984
2984
|
return reuseOk && releaseOk && encOk;
|
|
2985
2985
|
} },
|
|
2986
|
+
{ name: 'skill 트리거 description (1.36.25, obra/superpowers P0): BUILTIN_CATALOG 9/9 description(트리거 서술) + export/publish 합성 우선순위 description 우선 — 행위검사', run: () => {
|
|
2987
|
+
const c = require('../lib/catalogs');
|
|
2988
|
+
const ids = Object.keys(c.BUILTIN_CATALOG);
|
|
2989
|
+
// 9/9 description 존재 + 트리거 형태(ko "사용" + en "Use when") + 200자 슬라이스 생존 + displayNameKo 반복 아님
|
|
2990
|
+
const allDesc = ids.every(k => {
|
|
2991
|
+
const e = c.BUILTIN_CATALOG[k]; const d = e.description || '';
|
|
2992
|
+
return d.length >= 40 && d.length <= 200 && /사용/.test(d) && /Use when/i.test(d) && d !== e.displayNameKo;
|
|
2993
|
+
});
|
|
2994
|
+
// 합성 우선순위: description 이 displayNameKo 보다 먼저 (export 1 + publish 계열 2 = 총 3사이트)
|
|
2995
|
+
const s = read(__filename);
|
|
2996
|
+
const flipped = (s.match(/data\.description \|\| data\.displayNameKo/g) || []).length >= 3
|
|
2997
|
+
&& !s.includes('data.displayNameKo || ' + 'data.description'); // split-literal: 이 줄 자신이 매치되는 자기참조 트랩 회피
|
|
2998
|
+
return allDesc && flipped;
|
|
2999
|
+
} },
|
|
3000
|
+
{ name: 'requests positional 경로 (1.36.24, UR-0027 확장): requests 계열도 task/rule 과 동일하게 positional 경로 인식 — 다른 프로젝트 cwd 오기록 차단 — 소스가드+행위', run: () => {
|
|
3001
|
+
const s = read(__filename);
|
|
3002
|
+
const wired = s.includes("requestsCmd(arg('--path', null) || _taskPositionalPath(args, 2) || process.cwd()");
|
|
3003
|
+
// 행위(순수): path-like 만 경로 인정 — ID/텍스트/내부슬래시 무오인, 값-플래그 값 제외 (기존 계약 그대로)
|
|
3004
|
+
const p = require('../lib/pure-utils');
|
|
3005
|
+
const abs = p._taskPositionalPath(['requests', 'add', 'do the thing', 'C:\\other\\proj']) === 'C:\\other\\proj';
|
|
3006
|
+
const idNotPath = p._taskPositionalPath(['requests', 'drop', 'UR-0001']) === null;
|
|
3007
|
+
const innerSlashNotPath = p._taskPositionalPath(['requests', 'add', 'src/auth 모듈 정리']) === null;
|
|
3008
|
+
return wired && abs && idNotPath && innerSlashNotPath;
|
|
3009
|
+
} },
|
|
2986
3010
|
{ name: 'memory search 랭킹/동의어 (1.36.23): 한국어 조사 회귀 0 + 동의어 리콜 순증 + BM25 단조성 — 순수 행위검사', run: () => {
|
|
2987
3011
|
const sc = require('../lib/search-core');
|
|
2988
3012
|
const { MEMORY_SYNONYMS } = require('../lib/catalogs');
|
|
@@ -7612,7 +7636,7 @@ function skillExportCmd(root, id) {
|
|
|
7612
7636
|
if (!id) { fail('사용법: leerness skill export <id>'); return process.exit(1); }
|
|
7613
7637
|
const data = loadUserSkill(root, id) || (skillCatalog[id] ? { ...skillCatalog[id], name: id } : null);
|
|
7614
7638
|
if (!data) { fail(`skill 없음: ${id}`); return process.exit(1); }
|
|
7615
|
-
const description = data.
|
|
7639
|
+
const description = data.description || data.displayNameKo || (data.capabilities && data.capabilities[0]) || id; // 1.36.25 (P0): 트리거 서술 description 이 있으면 displayNameKo("~스킬")보다 우선 — 종전 순서는 좋은 description 을 무시했다
|
|
7616
7640
|
const body = `---\nname: ${id}\ndescription: ${description.slice(0, 200)}\n---\n\n# ${data.displayNameKo || id}\n\n## Capabilities\n${(data.capabilities || []).map(c => '- ' + c).join('\n') || '-'}\n\n## Sources\n${(data.sources || []).map(s => '- ' + (s.url || s)).join('\n') || '-'}\n\n## Patterns\n${(data.patterns || []).map(p => `- \`${p.command}\` — ${p.note || ''}`).join('\n') || '-'}\n`;
|
|
7617
7641
|
const outDir = arg('--out', path.join(root, '.harness', 'skills-export', id));
|
|
7618
7642
|
mkdirp(outDir);
|
|
@@ -16367,7 +16391,7 @@ function skillPublishCmd(root) {
|
|
|
16367
16391
|
// 각 skill을 SKILL.md로 export
|
|
16368
16392
|
for (const id of ids) {
|
|
16369
16393
|
const data = all[id];
|
|
16370
|
-
const description = (data.
|
|
16394
|
+
const description = (data.description || data.displayNameKo || (data.capabilities && data.capabilities[0]) || id).slice(0, 200); // 1.36.25 (P0): description(트리거 서술) 우선 — 종전 displayNameKo 1순위는 좋은 description 을 무시
|
|
16371
16395
|
const body = `---\nname: ${id}\ndescription: ${description}\nlicense: MIT\npublisher: leerness\nversion: ${VERSION}\n---\n\n# ${data.displayNameKo || id}\n\n## Capabilities\n${(data.capabilities || []).map(c => '- ' + c).join('\n') || '-'}\n\n## Sources\n${(data.sources || []).map(s => '- ' + (s.url || s)).join('\n') || '-'}\n\n## Usage\n\n\`\`\`bash\nleerness skill install <이 SKILL.md path or URL>\n\`\`\`\n`;
|
|
16372
16396
|
const skillDir = path.join(exportDir, id);
|
|
16373
16397
|
mkdirp(skillDir);
|
|
@@ -16961,7 +16985,7 @@ function skillExportAllCmd(root) {
|
|
|
16961
16985
|
log('');
|
|
16962
16986
|
for (const id of ids) {
|
|
16963
16987
|
const data = all[id];
|
|
16964
|
-
const description = (data.
|
|
16988
|
+
const description = (data.description || data.displayNameKo || (data.capabilities && data.capabilities[0]) || id).slice(0, 200); // 1.36.25 (P0): description(트리거 서술) 우선 — 종전 displayNameKo 1순위는 좋은 description 을 무시
|
|
16965
16989
|
const body = `---\nname: ${id}\ndescription: ${description}\n---\n\n# ${data.displayNameKo || id}\n\n## Capabilities\n${(data.capabilities || []).map(c => '- ' + c).join('\n') || '-'}\n\n## Sources\n${(data.sources || []).map(s => '- ' + (s.url || s)).join('\n') || '-'}\n`;
|
|
16966
16990
|
const skillDir = path.join(outDir, id);
|
|
16967
16991
|
mkdirp(skillDir);
|
|
@@ -21324,7 +21348,10 @@ async function main() {
|
|
|
21324
21348
|
// 1.9.203: leerness resume — auto-resume-plan 읽고 다음 라운드 즉시 안내 (사용자 명시)
|
|
21325
21349
|
if (cmd === 'resume') return resumeCmd(arg('--path', process.cwd()));
|
|
21326
21350
|
// 1.9.207: leerness requests <audit|add|list|complete|drop> — 사용자 요청 누락 확인 절차 (사용자 명시)
|
|
21327
|
-
|
|
21351
|
+
// 1.36.24 (UR-0027 확장, 실피해 재현): requests 계열만 positional 경로 미지원이라 `requests add "text" C:/other/proj` 가
|
|
21352
|
+
// 조용히 cwd 프로젝트에 기록하고 성공 보고했다(task/rule 은 _taskPositionalPath 지원 → 불일치가 실수를 유도, 본인 피해 확인).
|
|
21353
|
+
// rule 선례와 동일 배선 — path-like(선행 구분자) 만 인정하는 기존 계약이라 텍스트/ID 오인 FP 없음(_parseAddTitle 이 add 텍스트를 path-like 에서 끊는 것도 기존과 동일).
|
|
21354
|
+
if (cmd === 'requests') return requestsCmd(arg('--path', null) || _taskPositionalPath(args, 2) || process.cwd(), args[1], ...args.slice(2));
|
|
21328
21355
|
// 1.9.220: leerness session-resume — 비정상 종료 감지 + 자율 재개 가이드 (사용자 명시)
|
|
21329
21356
|
if (cmd === 'session-resume') return sessionResumeCmd(arg('--path', process.cwd()));
|
|
21330
21357
|
// 1.9.226: leerness round-history — 자율 라운드 통계 + 다음 마일스톤
|
package/lib/catalogs.js
CHANGED
|
@@ -349,16 +349,16 @@ const STRINGS = {
|
|
|
349
349
|
|
|
350
350
|
// 1.9.341 (UR-0025 심층): 내장 스킬 catalog (9종) — harness 에서 분리. _loadSkillCatalog 의 builtin fallback.
|
|
351
351
|
const BUILTIN_CATALOG = {
|
|
352
|
-
'office': { displayNameKo: '마이크로소프트 오피스 자동화 스킬 라이브러리', version: '1.0.0', lastUpdated: '2026-05-08', verification: 'passed', capabilities: ['Word/Excel/PowerPoint 문서 자동화', '템플릿 기반 문서 생성', '표/차트/요약 문서화', '민감정보 제외 규칙 적용'] },
|
|
353
|
-
'commerce-api': { displayNameKo: '커머스 API 연동 스킬 라이브러리', version: '1.0.0', lastUpdated: '2026-05-08', verification: 'passed', capabilities: ['쿠팡·롯데온·스마트스토어 API 연동 설계', '주문/상품/매출 동기화', '환경변수 기반 인증 분리', '레이트리밋/재시도/오류 처리'] },
|
|
354
|
-
'crawling': { displayNameKo: '크롤링·브라우저 자동화 스킬 라이브러리', version: '1.0.0', lastUpdated: '2026-05-08', verification: 'passed', capabilities: ['Playwright 기반 자동화', '다운로드/로그인 세션 처리', '스크린샷 기반 실패 진단', '약관/권한/차단 위험 점검'] },
|
|
355
|
-
'firebase': { displayNameKo: 'Firebase·Cloud Functions 스킬 라이브러리', version: '1.0.0', lastUpdated: '2026-05-08', verification: 'passed', capabilities: ['Firebase Functions 배포 구조', '환경변수/시크릿 분리', '권한/IAM 점검', '로컬 에뮬레이터 검증'] },
|
|
356
|
-
'ads-analytics': { displayNameKo: '광고·GA4 분석 스킬 라이브러리', version: '1.0.0', lastUpdated: '2026-05-08', verification: 'passed', capabilities: ['GA4 이벤트/전환 점검', '광고 데이터 수집 구조화', '소스/매체 분석', '리포트 자동화'] },
|
|
357
|
-
'appstore-review': { displayNameKo: '앱스토어 심사 대응 스킬 라이브러리', version: '1.0.0', lastUpdated: '2026-05-08', verification: 'passed', capabilities: ['심사 문구 분석', '개인정보 라벨 점검', '리젝 대응 초안', '웹뷰/앱 데이터 수집 구분'] },
|
|
358
|
-
'ai-verified-skill-publisher': { displayNameKo: 'AI 검증 스킬 업로드·라이브러리화 스킬', version: '1.0.0', lastUpdated: '2026-05-08', verification: 'passed', capabilities: ['검증된 스킬 정규화', '민감정보 스캔', 'AI 검증 메타데이터 작성', 'npm/git 업로드 dry-run 및 실행 게이트'] },
|
|
359
|
-
'feature-implementation': { displayNameKo: '기능 구현 표준 스킬', version: '1.0.0', lastUpdated: '2026-05-08', verification: 'passed', capabilities: ['feature-contracts 작성', '재사용 우선 검사', '테스트 증거 수집', '핸드오프 트리거'] },
|
|
352
|
+
'office': { displayNameKo: '마이크로소프트 오피스 자동화 스킬 라이브러리', description: '문서 산출물이 필요할 때 사용 — Word/Excel/PowerPoint 파일을 만들거나 편집하거나 템플릿으로 문서를 뽑아야 할 때. Use when the task produces or edits Office documents.', version: '1.0.0', lastUpdated: '2026-05-08', verification: 'passed', capabilities: ['Word/Excel/PowerPoint 문서 자동화', '템플릿 기반 문서 생성', '표/차트/요약 문서화', '민감정보 제외 규칙 적용'] },
|
|
353
|
+
'commerce-api': { displayNameKo: '커머스 API 연동 스킬 라이브러리', description: '커머스 플랫폼(쿠팡·롯데온·스마트스토어) API 를 붙일 때 사용 — 주문/상품/매출 연동 설계나 인증·레이트리밋 처리가 필요할 때. Use when integrating commerce platform APIs.', version: '1.0.0', lastUpdated: '2026-05-08', verification: 'passed', capabilities: ['쿠팡·롯데온·스마트스토어 API 연동 설계', '주문/상품/매출 동기화', '환경변수 기반 인증 분리', '레이트리밋/재시도/오류 처리'] },
|
|
354
|
+
'crawling': { displayNameKo: '크롤링·브라우저 자동화 스킬 라이브러리', description: '웹 페이지를 자동으로 조작·수집해야 할 때 사용 — 로그인 세션, 다운로드, 스크린샷 진단, 차단 위험 점검이 걸린 작업일 때. Use when the task drives or scrapes web pages.', version: '1.0.0', lastUpdated: '2026-05-08', verification: 'passed', capabilities: ['Playwright 기반 자동화', '다운로드/로그인 세션 처리', '스크린샷 기반 실패 진단', '약관/권한/차단 위험 점검'] },
|
|
355
|
+
'firebase': { displayNameKo: 'Firebase·Cloud Functions 스킬 라이브러리', description: 'Firebase/Cloud Functions 작업을 시작할 때 사용 — Functions 배포 구조, 시크릿 분리, IAM 점검, 에뮬레이터 검증이 필요할 때. Use when deploying or configuring Firebase.', version: '1.0.0', lastUpdated: '2026-05-08', verification: 'passed', capabilities: ['Firebase Functions 배포 구조', '환경변수/시크릿 분리', '권한/IAM 점검', '로컬 에뮬레이터 검증'] },
|
|
356
|
+
'ads-analytics': { displayNameKo: '광고·GA4 분석 스킬 라이브러리', description: '광고·GA4 데이터를 다룰 때 사용 — 이벤트/전환 점검, 광고 데이터 수집, 소스·매체 분석 리포트가 필요할 때. Use when analyzing ads or GA4 data.', version: '1.0.0', lastUpdated: '2026-05-08', verification: 'passed', capabilities: ['GA4 이벤트/전환 점검', '광고 데이터 수집 구조화', '소스/매체 분석', '리포트 자동화'] },
|
|
357
|
+
'appstore-review': { displayNameKo: '앱스토어 심사 대응 스킬 라이브러리', description: '앱스토어 심사를 준비하거나 리젝에 대응할 때 사용 — 심사 문구 분석, 개인정보 라벨 점검이 필요할 때. Use when preparing for or responding to app store review.', version: '1.0.0', lastUpdated: '2026-05-08', verification: 'passed', capabilities: ['심사 문구 분석', '개인정보 라벨 점검', '리젝 대응 초안', '웹뷰/앱 데이터 수집 구분'] },
|
|
358
|
+
'ai-verified-skill-publisher': { displayNameKo: 'AI 검증 스킬 업로드·라이브러리화 스킬', description: '검증된 스킬을 라이브러리로 정규화해 업로드할 때 사용 — 민감정보 스캔과 업로드 게이트가 필요할 때. Use when publishing a verified skill to a library.', version: '1.0.0', lastUpdated: '2026-05-08', verification: 'passed', capabilities: ['검증된 스킬 정규화', '민감정보 스캔', 'AI 검증 메타데이터 작성', 'npm/git 업로드 dry-run 및 실행 게이트'] },
|
|
359
|
+
'feature-implementation': { displayNameKo: '기능 구현 표준 스킬', description: '새 기능 구현을 시작할 때 사용 — feature-contract 작성, 재사용 우선 검사, 테스트 증거 수집이 필요한 구현 작업일 때. Use when starting to implement a new feature.', version: '1.0.0', lastUpdated: '2026-05-08', verification: 'passed', capabilities: ['feature-contracts 작성', '재사용 우선 검사', '테스트 증거 수집', '핸드오프 트리거'] },
|
|
360
360
|
// 1.9.11: 기본 내장 — 로드맵 자동 생성 스킬
|
|
361
|
-
'project-roadmap-generator': { displayNameKo: '프로젝트 로드맵 자동 생성 스킬', version: '0.2.0', lastUpdated: '2026-05-12', verification: 'passed', capabilities: ['leerness .harness/* 통합 파싱 (plan/progress/skills/rules/decisions/handoff/current-state)', '좌→우 수평 트리 + 상하 중앙정렬 SVG', '7개 상태 색상 (완료/진행/보류/검토/예정/미완료/오류)', 'design-system + CSS variables 자동 주입', '화이트보드 panning/zoom + 더블클릭 reset', '단일 HTML 출력 (외부 의존성 0)'] }
|
|
361
|
+
'project-roadmap-generator': { displayNameKo: '프로젝트 로드맵 자동 생성 스킬', description: '프로젝트 진행 상황을 로드맵 한 장으로 시각화해 달라고 할 때 사용 — .harness 상태를 SVG 트리 HTML 로 뽑을 때. Use when the user asks for a visual roadmap.', version: '0.2.0', lastUpdated: '2026-05-12', verification: 'passed', capabilities: ['leerness .harness/* 통합 파싱 (plan/progress/skills/rules/decisions/handoff/current-state)', '좌→우 수평 트리 + 상하 중앙정렬 SVG', '7개 상태 색상 (완료/진행/보류/검토/예정/미완료/오류)', 'design-system + CSS variables 자동 주입', '화이트보드 panning/zoom + 더블클릭 reset', '단일 HTML 출력 (외부 의존성 0)'] }
|
|
362
362
|
};
|
|
363
363
|
|
|
364
364
|
// 1.9.342 (UR-0025 심층): roadmap.html 상태 라벨/색상 맵 (status → ko 라벨 / hex 색상) — harness 에서 분리.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "leerness",
|
|
3
|
-
"version": "1.36.
|
|
3
|
+
"version": "1.36.25",
|
|
4
4
|
"description": "The AI-coding operations layer that makes \"done\" require evidence — persistent memory, evidence-gated completion checks, and clean handoffs for any AI agent (Claude Code, Codex, Cursor). State lives as plain files in your repo. CLI + MCP, 0 runtime dependencies.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"leerness",
|