agent-work-loop 0.6.46 → 0.6.47

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,13 +1,32 @@
1
1
  # agent-work-loop
2
2
 
3
- `agent-work-loop`(명령어: `awl`)은 AI 에이전트가 같은 실패를 두 번 반복하지 않도록 돕는 도구입니다. 에이전트가 작업하며 남긴 기록, 검증 결과, 완료 조건, 규칙, 교훈, 막힘을 파일로 관리합니다.
3
+ [![npm version](https://img.shields.io/npm/v/agent-work-loop.svg)](https://www.npmjs.com/package/agent-work-loop)
4
+ [![CI](https://github.com/kh1012/agent-work-loop/actions/workflows/ci.yml/badge.svg)](https://github.com/kh1012/agent-work-loop/actions/workflows/ci.yml)
5
+ [![release](https://img.shields.io/github/v/tag/kh1012/agent-work-loop?label=release&sort=semver)](https://github.com/kh1012/agent-work-loop/tags)
6
+ [![license](https://img.shields.io/npm/l/agent-work-loop.svg)](LICENSE)
4
7
 
5
- README는 **실용 문서**입니다. 설치부터 루프까지, 손으로 따라 있는 순서만 다룹니다. "왜 이렇게 만들었는가"(하네스 개념, 게이트 위치, narrative 실증 사례)는 [`docs/presentation/storyline.md`](docs/presentation/storyline.md)에 따로 정리했습니다. 명령어 하나하나의 자세한 사용법은 [`docs/presentation/commands.md`](docs/presentation/commands.md)를 참고하세요.
8
+ `agent-work-loop`(명령어: `awl`)은 AI 에이전트가 같은 실패를 반복하지 않도록 돕는 도구입니다. 에이전트가 작업하며 남긴 기록, 검증 결과, 완료 조건, 규칙, 교훈, 막힘을 파일로 관리합니다.
6
9
 
7
10
  **awl 자체는 판단하지 않습니다.** LLM을 호출하지 않고, 파일과 상태만 결정적으로 다룹니다. 무엇을 배우고 어떤 규칙을 세울지는 이미 설치된 에이전트(Claude Code, Codex)가 스킬로 판단합니다.
8
11
 
12
+ 이 README는 **실용 문서**입니다. 설치부터 첫 루프까지, 손으로 따라 할 수 있는 순서만 다룹니다. "왜 이렇게 만들었는가"(하네스 개념, 게이트 위치, narrative 실증 사례)는 [`docs/presentation/storyline.md`](docs/presentation/storyline.md)에, 명령어 하나하나의 자세한 사용법은 [`docs/presentation/commands.md`](docs/presentation/commands.md)에 정리했습니다.
13
+
9
14
  크로스 환경을 처음부터 전제로 합니다. macOS와 Windows, Claude Code와 Codex를 모두 지원하는 것을 목표로 합니다(Windows는 아직 macOS만큼 검증되지 않았습니다. [알려진 위험](docs/decisions.md)을 참고하세요).
10
15
 
16
+ ## 목차
17
+
18
+ - [언제 쓰나](#언제-쓰나)
19
+ - [설치](#설치)
20
+ - [5분 시작](#5분-시작)
21
+ - [LLM과 함께 실제로 쓰는 시나리오](#llm과-함께-실제로-쓰는-시나리오)
22
+ - [명령어 요약](#명령어-요약)
23
+ - [설정(config): 검증 명령과 모노레포](#설정config-검증-명령과-모노레포)
24
+ - [무엇이 어디에 쌓이나](#무엇이-어디에-쌓이나)
25
+ - [워크아이템 병행](#워크아이템-병행)
26
+ - [오케스트레이션 파이프라인: 여러 레인을 나란히](#오케스트레이션-파이프라인-여러-레인을-나란히)
27
+ - [문제 해결](#문제-해결)
28
+ - [기여하기](#기여하기)
29
+
11
30
  ---
12
31
 
13
32
  ## 언제 쓰나
@@ -35,32 +54,26 @@ yarn global add agent-work-loop
35
54
 
36
55
  > **pnpm 함정**: pnpm으로 전역 설치하면 `awl` 명령을 찾을 수 없다는 에러가 날 수 있습니다. pnpm의 전역 bin 디렉토리가 PATH에 없어서입니다. `pnpm setup`을 한 번 실행하고 터미널을 새로 열면 해결됩니다.
37
56
 
38
- > **팀 내부 설치(지금 당장 필요하면)**: 이 README를 작성하는 시점 기준으로 npm 레지스트리의 `agent-work-loop`는 아직 `0.0.0`(이름 예약용 placeholder)만 배포돼 있어 `npm install -g agent-work-loop`로는 동작하는 CLI가 설치되지 않습니다. 지금 바로 써야 한다면 이 저장소를 클론해 직접 빌드·링크하세요.
39
- > ```bash
40
- > git clone <이 저장소> && cd agent-work-loop
41
- > pnpm install && pnpm run build
42
- > pnpm link --global # 또는: npm link
43
- > ```
44
- > `dist/cli.js`가 `awl` bin으로 등록됩니다. 정식 npm 배포가 되면 이 문단은 지웁니다.
57
+ 저장소를 직접 빌드해서 쓰고 싶다면(기여하거나 배포 최신 상태를 바로 써보고 싶을 때):
45
58
 
46
- ### 업데이트 하기
47
-
48
- ```
49
- 업데이트 하기:
50
- 1. npm i -g agent-work-loop@latest npm에 배포된 최신 버전을 받습니다
51
- 2. awl update 설치된 패키지로 전역 엔진(~/.awl/engine)을 갱신합니다
59
+ ```bash
60
+ git clone https://github.com/kh1012/agent-work-loop.git && cd agent-work-loop
61
+ pnpm install && pnpm run build
62
+ pnpm link --global # 또는: npm link
52
63
  ```
53
64
 
54
- pnpm이나 yarn을 쓴다면 1번만 그 도구로 바꿉니다:
65
+ `dist/cli.js`가 `awl` bin으로 등록됩니다.
55
66
 
56
- ```bash
57
- pnpm add -g agent-work-loop@latest
58
- yarn global add agent-work-loop@latest
67
+ ### 업데이트 하기
68
+
69
+ ```
70
+ 1. npm i -g agent-work-loop@latest npm에 배포된 최신 버전을 받습니다
71
+ 2. awl update 설치된 패키지로 전역 엔진(~/.awl/engine)을 갱신합니다
59
72
  ```
60
73
 
61
- `awl update`(옵션 없음)는 `awl update --global`과 같습니다. 전역 엔진만 갱신하고 어떤 프로젝트도 건드리지 않습니다. 대부분은 이 두 줄이면 끝입니다.
74
+ pnpm이나 yarn을 쓴다면 1번만 그 도구로 바꿉니다. `awl update`(옵션 없음)는 `awl update --global`과 같습니다. 전역 엔진만 갱신하고 어떤 프로젝트도 건드리지 않습니다. 대부분은 이 두 줄이면 끝입니다.
62
75
 
63
- **여러 프로젝트를 관리하는 입장이라면** 등록된 프로젝트들의 로컬 스킬(`.claude/skills`, `AGENTS.md`, `.awl/config.json`)까지 한 번에 맞추고 싶을 수 있습니다:
76
+ **여러 프로젝트를 관리하는 입장이라면** 등록된 프로젝트들의 로컬 스킬(`.claude/skills`, `AGENTS.md`, `.awl/config.json`)까지 한 번에 맞추고 싶을 수 있습니다.
64
77
 
65
78
  ```bash
66
79
  npm i -g agent-work-loop@latest
@@ -71,12 +84,12 @@ awl update --all
71
84
 
72
85
  이렇게 갱신한 프로젝트를 커밋해서 push하면, 그 저장소를 쓰는 다른 사람들은 다음에 pull할 때 최신 스킬을 받습니다. **다만 자동으로 알림이 가는 구조는 아닙니다.** 각자 컴퓨터의 `~/.awl/engine`이 낡았는지는 그 사람이 `awl doctor`/`awl version-check`를 실행하거나 `/awl-loop`·`/awl-pipeline`을 실행할 때(버전 확인이 맨 처음 단계로 들어있습니다) 노란 경고로 보게 됩니다.
73
86
 
74
- 설치가 됐는지 확인합니다:
87
+ 설치가 됐는지 확인합니다.
75
88
 
76
89
  ```bash
77
90
  $ awl doctor
78
91
 
79
- +- Agent Work Loop · 진단 ------------------------------------------------------------------+
92
+ + Agent Work Loop · 진단
80
93
  | 환경
81
94
  | |-- Node: v22.22.2 [ok]
82
95
  | |-- 플랫폼: darwin arm64 [ok]
@@ -92,10 +105,10 @@ $ awl doctor
92
105
  |
93
106
  | 에이전트
94
107
  | |-- Claude Code: 없음
95
- | |-- Codex: 없음
108
+ | `-- Codex: 없음
96
109
  |
97
110
  | [x] 문제 2개. awl init 을 실행하세요.
98
- +-------------------------------------------------------------------------------------------+
111
+ +
99
112
  ```
100
113
 
101
114
  터미널이 유니코드/색을 지원하면(Windows Terminal, VS Code 터미널 등) 자동으로 감지해 상자 그림과 색을 씁니다. 지원 안 되면 위처럼 ASCII로 자동 전환됩니다. `doctor`는 아무것도 고치지 않습니다. 점검만 합니다.
@@ -111,22 +124,26 @@ $ cd my-project
111
124
  $ awl init
112
125
  ```
113
126
 
114
- 질문 없이 감지된 값으로 바로 진행하려면 `awl init --yes`를 씁니다. 실제 출력(스크래치 프로젝트, `--yes`):
127
+ 질문 없이 감지된 값으로 바로 진행하려면 `awl init --yes`를 씁니다. 실제 출력:
115
128
 
116
129
  ```
117
- +- 설정 완료 ---------------------------------------------------------------+
118
- | ~/.awl 생성됨 |
119
- | ~/.awl/engine 0.6.18 |
120
- | .awl/config.json 생성됨 <- 커밋하세요. 팀원은 이 파일을 씁니다 |
121
- | .awl/state.json gitignore 에 추가함 [ok] git push 차단 설치 |
122
- | 규칙 0개 · 교훈 0개 · 등록된 프로젝트 1개 · 1세대 |
123
- +---------------------------------------------------------------------------+
124
-
125
- +- 다음 단계 ----------------------------------------------------+
126
- | Claude Code 를 열고 이렇게 말하세요. |
127
- | |
128
- | /awl-loop 페이지 편집기에 여백 시스템을 넣고 싶어 |
129
- +----------------------------------------------------------------+
130
+ + 설정 완료
131
+ | [v0.6.46]
132
+ | ~/.awl 생성됨
133
+ | ~/.awl/engine 0.6.46
134
+ | .awl/config.json 생성됨 <- 커밋하세요. 팀원은 파일을 씁니다
135
+ | .awl/state.json gitignore 추가함 [ok] git push 차단 설치
136
+ | 규칙 0개 · 교훈 0개 · 등록된 프로젝트 1개 · 1세대
137
+ +
138
+
139
+ + 다음 단계
140
+ | Claude Code 를 열고 이렇게 말하세요.
141
+ |
142
+ | /awl-loop 페이지 편집기에 여백 시스템을 넣고 싶어
143
+ |
144
+ | /awl-pipeline <레인명> --gl 을 실행해보세요.
145
+ | (격리된 작업 세션이 생성되며, 자율 모드로 실행됩니다.)
146
+ +
130
147
  ```
131
148
 
132
149
  대화형 모드(`--yes` 없이)는 3단계 화면(1/3 주 언어 → 2/3 검증 명령어 → 3/3 규칙과 이 프로젝트의 성격)을 방향키(또는 번호)로 물은 뒤, 설치할 에이전트를 고르는 스킬 화면을 보여줍니다.
@@ -150,6 +167,13 @@ $ awl init
150
167
  awl status # 지금 어디까지 왔는지 한눈에
151
168
  ```
152
169
 
170
+ 명령어 전체와 스킬(`/awl-loop`·`/awl-pipeline`) 부연설명은 CLI 안에서도 바로 볼 수 있습니다.
171
+
172
+ ```bash
173
+ awl --examples # 자주 쓰는 명령 예시
174
+ awl --skills # /awl-loop·/awl-pipeline·레인·게이트 밀도(<mode>) 설명
175
+ ```
176
+
153
177
  ---
154
178
 
155
179
  ## LLM과 함께 실제로 쓰는 시나리오
@@ -198,10 +222,10 @@ awl status # 지금 어디까지 왔는지 한눈에
198
222
  ```bash
199
223
  awl records --json # 있었던 일 전수(타입·워크아이템으로 필터 가능)
200
224
  awl gotchas # 아직 규칙 안 된 교훈
201
- awl rules # 이 프로젝트에 적용되는 규칙
202
- awl metrics --compare # 워크아이템 세대별 지표 추세
203
- awl brief # 오늘(KST) 진행분만 모아 보기
204
- awl defer-summary # gate-medium/gate-low에서 보류된 중요 항목 최종 확인
225
+ awl rules # 이 프로젝트에 적용되는 규칙
226
+ awl metrics --compare # 워크아이템 세대별 지표 추세
227
+ awl brief # 오늘(KST) 진행분만 모아 보기
228
+ awl defer-summary # gate-medium/gate-low에서 보류된 중요 항목 최종 확인
205
229
  ```
206
230
 
207
231
  `~/.awl`을 직접 열어보면 이렇게 생겼습니다.
@@ -223,7 +247,7 @@ awl defer-summary # gate-medium/gate-low에서 보류된 중요 항목 최
223
247
 
224
248
  ## 명령어 요약
225
249
 
226
- 자주 쓰는 것만 적습니다. 25개 명령(사람용 17 + 스킬용 8) 전부와 실제 실행 예시는 [`commands.md`](docs/presentation/commands.md) 있습니다.
250
+ 자주 쓰는 것만 적습니다. 전체 명령과 실제 실행 예시는 [`commands.md`](docs/presentation/commands.md)에, `awl --examples`로도 바로 볼 수 있습니다.
227
251
 
228
252
  ```bash
229
253
  awl status # 지금 어디까지 왔는지
@@ -245,7 +269,7 @@ awl feedback-log # awl 도구 자체에 남겨진 피드백 기록 검토
245
269
  ```json
246
270
  {
247
271
  "project": "my-project",
248
- "mainLanguage": "typescript",
272
+ "mainLanguage": ["typescript"],
249
273
  "character": "디자인 토큰 강제, 여백은 자유 px 금지",
250
274
  "verify": {
251
275
  "typecheck": { "cmd": "tsc --noEmit" },
@@ -286,11 +310,11 @@ $ awl config set verify.typecheck.cwd packages/app
286
310
  |---|---|---|
287
311
  | 담는 것 | 엔진(스킬 템플릿), 규칙, 교훈(gotcha), 기록(records), 등록된 프로젝트 목록 | 이 프로젝트의 설정(config.json), 지금 루프 위치(state.json) |
288
312
  | 누구 것인가 | **당신**. 프로젝트를 옮겨 다녀도 따라옵니다 | **이 프로젝트**. 리포지토리를 나가면 안 따라옵니다 |
289
- | git 커밋 | 대상 아님(홈 디렉토리) | `config.json`은 커밋, `state.json`은 gitignore |
313
+ | git 커밋 | 대상 아님(홈 디렉토리) | 프로젝트마다 다름 — `state.json`은 항상 gitignore, `config.json`은 팀 컨벤션에 따라 커밋하거나 로컬 전용으로 gitignore 수 있습니다 |
290
314
 
291
315
  두 층으로 나눈 이유(다음 프로젝트에서 빈손으로 시작하지 않기 위해)와 규칙/교훈이 어떻게 승격되는지는 [`storyline.md` 4절·5절](docs/presentation/storyline.md)에서 다룹니다. `AWL_HOME` 환경변수로 전역 위치를 바꿀 수 있습니다(테스트·CI에서 유용합니다).
292
316
 
293
- 규칙 승격은 사람이 직접 합니다(자동 승격 없음):
317
+ 규칙 승격은 사람이 직접 합니다(자동 승격 없음).
294
318
 
295
319
  ```bash
296
320
  awl rules promote G-003 \
@@ -298,7 +322,7 @@ awl rules promote G-003 \
298
322
  --counter "이미 디자인 토큰 시스템이 없는 프로젝트"
299
323
  ```
300
324
 
301
- 교훈(gotcha, `~/.awl/gotchas`)과 awl 도구 자체 피드백(`~/.awl/records`, `awl record awl-feedback`)은 다른 종류입니다. 전자는 작업 대상 코드에 대한 것이고, 후자는 "awl commit이 이래서 아팠다" 같은 도구 자체의 문제입니다.
325
+ 교훈(gotcha, `~/.awl/gotchas`)과 awl 도구 자체 피드백(`~/.awl/records`, `awl record awl-feedback`)은 다른 종류입니다. 전자는 작업 대상 코드에 대한 것이고, 후자는 "awl commit이 이래서 아팠다" 같은 도구 자체의 문제입니다. `awl feedback-log`로 모아 봅니다.
302
326
 
303
327
  ---
304
328
 
@@ -335,9 +359,6 @@ awl work switch <ID> # 보관된 워크아이템으로 전환
335
359
  **`awl: command not found` (pnpm 설치 후)**
336
360
  `pnpm setup`을 실행하고 터미널을 새로 엽니다. pnpm 전역 bin이 PATH에 없어서입니다.
337
361
 
338
- **`npm install -g agent-work-loop`를 했는데 `awl`이 아무것도 못 한다**
339
- 위 설치 섹션을 참고하세요. 아직 npm에 `0.0.0` placeholder만 배포돼 있습니다. 저장소를 클론해 `pnpm install && pnpm run build && pnpm link --global`로 설치하세요.
340
-
341
362
  **`awl --version`이 엔진 버전 불일치를 경고한다**
342
363
  `awl`을 업그레이드했는데 `~/.awl/engine`은 예전 버전 그대로일 때 나옵니다. `awl update`로 엔진을 갱신하면 맞춰집니다(프로젝트 설정은 안 건드립니다). `awl version-check`로 어긋난 버전 쌍(package.json, 설치된 엔진, 프로젝트 config, 설치된 스킬)을 직접 봅니다. 프로젝트 config가 엔진보다 낡았다면 `awl init --yes`를 다시 실행합니다.
343
364
 
@@ -357,10 +378,7 @@ awl work switch <ID> # 보관된 워크아이템으로 전환
357
378
  `awl init`이 심는 pre-push 훅 때문입니다(위 5분 시작 참고). 실제 터미널에서 사람이 직접 치는 push는 막히지 않습니다 — 막혔다면 비대화형(에이전트, CI, 스크립트)으로 실행된 경우이고, 그때는 `AWL_ALLOW_PUSH=1 git push`를 씁니다.
358
379
 
359
380
  **대형 저장소에서 `awl lane new`/`awl work new --worktree`가 `Could not write new index file`로 실패한다**
360
- `git worktree add`가 기본 180초 안에 못 끝나 강제 종료됐다는 뜻입니다(대형 모노레포는
361
- 체크아웃이 오래 걸립니다) — 디스크 문제가 아닙니다. `AWL_GIT_WORKTREE_TIMEOUT_MS=<ms>`
362
- 환경변수로 값을 늘려 다시 시도하세요(예: `AWL_GIT_WORKTREE_TIMEOUT_MS=300000 awl lane new
363
- <이름>`).
381
+ `git worktree add`가 기본 180초 안에 못 끝나 강제 종료됐다는 뜻입니다(대형 모노레포는 체크아웃이 오래 걸립니다) — 디스크 문제가 아닙니다. `AWL_GIT_WORKTREE_TIMEOUT_MS=<ms>` 환경변수로 값을 늘려 다시 시도하세요(예: `AWL_GIT_WORKTREE_TIMEOUT_MS=300000 awl lane new <이름>`).
364
382
 
365
383
  **게이트에서 스킬이 안 멈추고 그냥 진행한다**
366
384
  스킬 문서가 게이트에서 반드시 도구를 호출하도록 지시돼 있습니다. 계속 안 멈추면 스킬이 최신인지 확인하세요. `awl doctor`가 `claude-skill-vs-engine` 불일치를 경고하면 `awl init --yes`로 재설치합니다.
@@ -370,7 +388,7 @@ awl work switch <ID> # 보관된 워크아이템으로 전환
370
388
 
371
389
  ---
372
390
 
373
- ## 기여 / 라이선스
391
+ ## 기여하기
374
392
 
375
393
  이 저장소는 pnpm을 사용합니다.
376
394
 
@@ -382,8 +400,10 @@ pnpm run lint # biome 검사
382
400
  pnpm run typecheck
383
401
  ```
384
402
 
403
+ PR을 올리면 [GitHub Actions](.github/workflows/ci.yml)가 Node 18/22 두 버전에서 typecheck·lint·test·build를 자동으로 돌립니다.
404
+
385
405
  릴리스는 `pnpm release:patch` / `pnpm release:minor` / `pnpm release:major`로 합니다. 검증·빌드·tarball·`npm publish --dry-run`을 통과한 뒤 버전, CHANGELOG, 커밋, 태그, 원격 push를 한 번에 처리합니다. **`npm publish`만 사람이 실행합니다.**
386
406
 
387
407
  npm에 `awl` 패키지가 이미 있어, 패키지 이름은 `agent-work-loop`로 배포하고 명령어 이름만 `awl`로 씁니다.
388
408
 
389
- 라이선스는 MIT입니다.
409
+ 라이선스는 [MIT](LICENSE)입니다.
@@ -13,10 +13,10 @@ import {
13
13
  isCheckPassed,
14
14
  runVerifyChecks,
15
15
  writeVerifyBaseline
16
- } from "./chunk-WWZIKKHP.js";
16
+ } from "./chunk-NCS2EPDP.js";
17
17
  import {
18
18
  gitBranch
19
- } from "./chunk-DA27NBCS.js";
19
+ } from "./chunk-R4UNIGE5.js";
20
20
  import {
21
21
  loadProjectName
22
22
  } from "./chunk-FK3Q7UY2.js";
@@ -3,7 +3,7 @@ import {
3
3
  } from "./chunk-VVZOIFL4.js";
4
4
  import {
5
5
  gitDirtyFiles
6
- } from "./chunk-DA27NBCS.js";
6
+ } from "./chunk-R4UNIGE5.js";
7
7
  import {
8
8
  applyVerificationAttempts,
9
9
  loadState,
@@ -8,10 +8,10 @@ import {
8
8
  } from "./chunk-VE2GVNNS.js";
9
9
  import {
10
10
  gatherVersionInputs
11
- } from "./chunk-XWMS6Z5E.js";
11
+ } from "./chunk-SFTVZFTQ.js";
12
12
  import {
13
13
  checkVersions
14
- } from "./chunk-ZEX5ZF6C.js";
14
+ } from "./chunk-YW64OU6W.js";
15
15
  import {
16
16
  CommandNotFoundError,
17
17
  run,
@@ -5,7 +5,7 @@ import {
5
5
  runWorkNew,
6
6
  sanitizeForGit,
7
7
  worktreeDirtyTracked
8
- } from "./chunk-AGFQC2UO.js";
8
+ } from "./chunk-5HXSUU6Y.js";
9
9
  import {
10
10
  loadProjectName
11
11
  } from "./chunk-FK3Q7UY2.js";
@@ -3,7 +3,7 @@ import {
3
3
  getLatestVersionCached,
4
4
  name,
5
5
  version
6
- } from "./chunk-ZEX5ZF6C.js";
6
+ } from "./chunk-YW64OU6W.js";
7
7
  import {
8
8
  resolveProjectRoot
9
9
  } from "./chunk-MLTY3EE6.js";
@@ -4,7 +4,7 @@ import {
4
4
 
5
5
  // package.json
6
6
  var name = "agent-work-loop";
7
- var version = "0.6.46";
7
+ var version = "0.6.47";
8
8
 
9
9
  // src/core/npm-registry.ts
10
10
  import fs from "fs";
package/dist/cli.js CHANGED
@@ -3,7 +3,7 @@ import {
3
3
  computeUpdateAvailable,
4
4
  readCachedLatestVersion,
5
5
  version
6
- } from "./chunk-ZEX5ZF6C.js";
6
+ } from "./chunk-YW64OU6W.js";
7
7
  import {
8
8
  caps,
9
9
  engineDir,
@@ -321,11 +321,11 @@ ${renderSkillsHelpFooter(caps())}
321
321
  await runBrief({ today: opts.today === true, date: opts.date, json: opts.json === true });
322
322
  });
323
323
  program.command("doctor").description("\uC124\uCE58\uC640 \uD658\uACBD\uC744 \uC810\uAC80\uD569\uB2C8\uB2E4 (\uC544\uBB34\uAC83\uB3C4 \uACE0\uCE58\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4)").option("--json", "\uAE30\uACC4\uAC00 \uC77D\uC744 \uC218 \uC788\uB294 JSON\uC73C\uB85C \uCD9C\uB825\uD569\uB2C8\uB2E4").action(async (opts) => {
324
- const { runDoctor } = await import("./doctor-JNUZJC6Z.js");
324
+ const { runDoctor } = await import("./doctor-3XCI22NM.js");
325
325
  await runDoctor({ json: opts.json === true });
326
326
  });
327
327
  program.command("version-check").description("\uBC84\uC804 \uBD88\uC77C\uCE58\uB97C \uAC80\uC0AC\uD569\uB2C8\uB2E4 (package/engine/\uD504\uB85C\uC81D\uD2B8/\uC2A4\uD0AC)").option("--json", "\uAE30\uACC4\uAC00 \uC77D\uC744 \uC218 \uC788\uB294 JSON\uC73C\uB85C \uCD9C\uB825\uD569\uB2C8\uB2E4").action(async (opts) => {
328
- const { runVersionCheck } = await import("./version-check-5BX3SO7G.js");
328
+ const { runVersionCheck } = await import("./version-check-ZVQZAJ5X.js");
329
329
  await runVersionCheck({ json: opts.json === true });
330
330
  });
331
331
  program.command("update").description(
@@ -339,7 +339,7 @@ ${renderSkillsHelpFooter(caps())}
339
339
  });
340
340
  program.command("remove").description("awl \uC774 \uC190\uB304 \uD754\uC801\uC744 \uC9C0\uC6C1\uB2C8\uB2E4 (\uAE30\uBCF8\uC740 \uB4DC\uB77C\uC774\uB7F0 \u2014 --yes \uC5C6\uC774\uB294 \uC0AD\uC81C\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4)").option("--yes", "\uC2E4\uC81C\uB85C \uC0AD\uC81C\uD569\uB2C8\uB2E4 (\uAE30\uBCF8\uC740 \uB4DC\uB77C\uC774\uB7F0)").option("--project", "\uC774 \uD504\uB85C\uC81D\uD2B8 \uB85C\uCEEC\uB9CC \uC815\uB9AC\uD569\uB2C8\uB2E4 (\uAE30\uBCF8\uAC12)").option("--global", "\uC804\uC5ED(~/.awl)\uB9CC \uC815\uB9AC\uD569\uB2C8\uB2E4 \u2014 \uB2E4\uB978 \uD504\uB85C\uC81D\uD2B8\uC758 \uD559\uC2B5\uB3C4 \uD568\uAED8 \uC0AC\uB77C\uC9D1\uB2C8\uB2E4").option("--all", "\uD504\uB85C\uC81D\uD2B8 \uB85C\uCEEC + \uC804\uC5ED\uC744 \uBAA8\uB450 \uC815\uB9AC\uD569\uB2C8\uB2E4").option("--json", "\uAE30\uACC4\uAC00 \uC77D\uC744 \uC218 \uC788\uB294 JSON\uC73C\uB85C \uCD9C\uB825\uD569\uB2C8\uB2E4").action(
341
341
  async (opts) => {
342
- const { runRemove } = await import("./remove-VJ7VBKTZ.js");
342
+ const { runRemove } = await import("./remove-SGQHBPW3.js");
343
343
  await runRemove({
344
344
  yes: opts.yes === true,
345
345
  project: opts.project === true,
@@ -362,11 +362,11 @@ ${renderSkillsHelpFooter(caps())}
362
362
  );
363
363
  const work = program.command("work").description("\uC774 \uD504\uB85C\uC81D\uD2B8\uC758 \uC6CC\uD06C\uC544\uC774\uD15C\uC744 \uAD00\uB9AC\uD569\uB2C8\uB2E4");
364
364
  work.option("--json", "\uAE30\uACC4\uAC00 \uC77D\uC744 \uC218 \uC788\uB294 JSON\uC73C\uB85C \uCD9C\uB825\uD569\uB2C8\uB2E4").action(async (opts) => {
365
- const { runWorkList } = await import("./work-3YHL3P6U.js");
365
+ const { runWorkList } = await import("./work-XO5RGFTG.js");
366
366
  runWorkList({ json: opts.json === true });
367
367
  });
368
368
  work.command("list").description("\uB4F1\uB85D\uB41C \uC6CC\uD06C\uC544\uC774\uD15C \uBAA9\uB85D\uACFC \uC9C4\uD589 \uC0C1\uD669\uC744 \uBD05\uB2C8\uB2E4").option("--json", "\uAE30\uACC4\uAC00 \uC77D\uC744 \uC218 \uC788\uB294 JSON\uC73C\uB85C \uCD9C\uB825\uD569\uB2C8\uB2E4").action(async (opts) => {
369
- const { runWorkList } = await import("./work-3YHL3P6U.js");
369
+ const { runWorkList } = await import("./work-XO5RGFTG.js");
370
370
  runWorkList({ json: opts.json === true });
371
371
  });
372
372
  work.command("new <id> [description]").description("\uC0C8 \uC6CC\uD06C\uC544\uC774\uD15C\uC744 \uB9CC\uB4E4\uACE0 \uC804\uD658\uD569\uB2C8\uB2E4 (\uD604\uC7AC \uC6CC\uD06C\uC544\uC774\uD15C\uC740 \uBCF4\uAD00\uB429\uB2C8\uB2E4)").option("--worktree [branch]", "\uACA9\uB9AC\uB41C git worktree \uB97C \uB9CC\uB4E4\uC5B4 \uADF8 \uC548\uC5D0\uC11C \uC2DC\uC791\uD569\uB2C8\uB2E4").option("--skip-baseline", "\uAC80\uC99D \uBCA0\uC774\uC2A4\uB77C\uC778 \uCEA1\uCC98\uB97C \uAC74\uB108\uB701\uB2C8\uB2E4 (\uB290\uB9B0 \uD504\uB85C\uC81D\uD2B8\uC6A9)").option(
@@ -374,7 +374,7 @@ ${renderSkillsHelpFooter(caps())}
374
374
  "records(~/.awl)\uB97C \uC774 \uC6CC\uD06C\uC544\uC774\uD15C \uC804\uC6A9 AWL_HOME \uC73C\uB85C \uACA9\uB9AC\uD569\uB2C8\uB2E4 (\uBCD1\uB82C \uC138\uC158\uC6A9)"
375
375
  ).option("--experiment <json>", '\uC2E4\uD5D8 \uCF00\uC774\uC2A4 \uBA54\uD0C0 JSON (\uC608: {"model":"lite","mode":"loop"})').action(
376
376
  async (id, description, opts) => {
377
- const { runWorkNew } = await import("./work-3YHL3P6U.js");
377
+ const { runWorkNew } = await import("./work-XO5RGFTG.js");
378
378
  const parsedExp = parseExperimentOption(opts.experiment);
379
379
  if (!parsedExp.ok) {
380
380
  process.stderr.write(`
@@ -386,34 +386,34 @@ ${renderSkillsHelpFooter(caps())}
386
386
  }
387
387
  );
388
388
  work.command("switch <id>").description("\uB2E4\uB978 \uC6CC\uD06C\uC544\uC774\uD15C\uC73C\uB85C \uC804\uD658\uD569\uB2C8\uB2E4 (\uD604\uC7AC \uC6CC\uD06C\uC544\uC774\uD15C\uC740 \uBCF4\uAD00\uB429\uB2C8\uB2E4)").action(async (id) => {
389
- const { runWorkSwitch } = await import("./work-3YHL3P6U.js");
389
+ const { runWorkSwitch } = await import("./work-XO5RGFTG.js");
390
390
  await runWorkSwitch(id);
391
391
  });
392
392
  work.command("abandon <id>").description("\uC6CC\uD06C\uC544\uC774\uD15C\uC744 \uC911\uB2E8 \uCC98\uB9AC\uD569\uB2C8\uB2E4 (\uC0AD\uC81C\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4, \uAE30\uB85D\uC740 \uB0A8\uC2B5\uB2C8\uB2E4)").action(async (id) => {
393
- const { runWorkAbandon } = await import("./work-3YHL3P6U.js");
393
+ const { runWorkAbandon } = await import("./work-XO5RGFTG.js");
394
394
  runWorkAbandon(id);
395
395
  });
396
396
  work.command("done <id>").description(
397
397
  "\uC644\uB8CC\uB41C \uC6CC\uD06C\uC544\uC774\uD15C\uC744 \uC815\uB9AC\uD569\uB2C8\uB2E4 (\uC6CC\uD06C\uD2B8\uB9AC \uC81C\uAC70 + \uC0C1\uD0DC \uC2A4\uB0C5\uC0F7 \uD68C\uC218, \uAE30\uB85D\uC740 \uB0A8\uC2B5\uB2C8\uB2E4)"
398
398
  ).option("--force", "\uC815\uB9AC\uB418\uC9C0 \uC54A\uC740 \uBCC0\uACBD\uC774 \uC788\uC5B4\uB3C4 \uC6CC\uD06C\uD2B8\uB9AC\uB97C \uC81C\uAC70\uD569\uB2C8\uB2E4").action(async (id, opts) => {
399
- const { runWorkDone } = await import("./work-3YHL3P6U.js");
399
+ const { runWorkDone } = await import("./work-XO5RGFTG.js");
400
400
  await runWorkDone(id, { force: opts.force === true });
401
401
  });
402
402
  const lane = program.command("lane").description("\uACA9\uB9AC \uB808\uC778(worktree)\uC73C\uB85C \uD30C\uC774\uD504\uB77C\uC778\uC744 \uBCD1\uB82C \uC2E4\uD589\uD569\uB2C8\uB2E4 (\uB808\uC778 \uC0DD\uC131\xB7\uC870\uD68C\xB7\uC815\uB9AC)");
403
403
  lane.option("--json", "\uAE30\uACC4\uAC00 \uC77D\uC744 \uC218 \uC788\uB294 JSON\uC73C\uB85C \uCD9C\uB825\uD569\uB2C8\uB2E4").action(async (opts) => {
404
- const { runLaneList } = await import("./lane-ETMPPVXP.js");
404
+ const { runLaneList } = await import("./lane-5CU25EAJ.js");
405
405
  await runLaneList({ json: opts.json === true });
406
406
  });
407
407
  lane.command("new <name> [description]").description("\uACA9\uB9AC \uB808\uC778\uC744 \uB9CC\uB4ED\uB2C8\uB2E4 (worktree + \uC804\uC6A9 AWL_HOME + \uC2A4\uD0AC \uC7AC\uC124\uCE58 + \uAE30\uB3D9 \uC548\uB0B4)").action(async (name, description) => {
408
- const { runLaneNew } = await import("./lane-ETMPPVXP.js");
408
+ const { runLaneNew } = await import("./lane-5CU25EAJ.js");
409
409
  await runLaneNew(name, description);
410
410
  });
411
411
  lane.command("ls").description("\uD604\uC874 \uB808\uC778\uC744 \uC774\uB984\xB7\uACBD\uB85C\xB7\uBE0C\uB79C\uCE58\uC640 \uD568\uAED8 \uB098\uC5F4\uD569\uB2C8\uB2E4").option("--json", "\uAE30\uACC4\uAC00 \uC77D\uC744 \uC218 \uC788\uB294 JSON\uC73C\uB85C \uCD9C\uB825\uD569\uB2C8\uB2E4").action(async (opts) => {
412
- const { runLaneList } = await import("./lane-ETMPPVXP.js");
412
+ const { runLaneList } = await import("./lane-5CU25EAJ.js");
413
413
  await runLaneList({ json: opts.json === true });
414
414
  });
415
415
  lane.command("rm <name>").description("\uB808\uC778\uC758 \uC6CC\uD06C\uD2B8\uB9AC\uB97C \uD68C\uC218\uD558\uACE0 \uB514\uB809\uD1A0\uB9AC\uB97C \uC81C\uAC70\uD569\uB2C8\uB2E4").option("--force", "\uCEE4\uBC0B\uB418\uC9C0 \uC54A\uC740 \uBCC0\uACBD\uC774 \uC788\uC5B4\uB3C4 \uC81C\uAC70\uD569\uB2C8\uB2E4").action(async (name, opts) => {
416
- const { runLaneRemove } = await import("./lane-ETMPPVXP.js");
416
+ const { runLaneRemove } = await import("./lane-5CU25EAJ.js");
417
417
  await runLaneRemove(name, { force: opts.force === true });
418
418
  });
419
419
  program.command("records").description("\uC313\uC778 \uAE30\uB85D\uC744 \uBD05\uB2C8\uB2E4").option("--type <type>", "\uD0C0\uC785\uC73C\uB85C \uAC70\uB985\uB2C8\uB2E4 (attempt, blocked \uB4F1)").option("--workitem <id>", "\uC6CC\uD06C\uC544\uC774\uD15C\uC73C\uB85C \uAC70\uB985\uB2C8\uB2E4").option("--json", "\uAE30\uACC4\uAC00 \uC77D\uC744 \uC218 \uC788\uB294 JSON\uC73C\uB85C \uCD9C\uB825\uD569\uB2C8\uB2E4").action(async (opts) => {
@@ -485,7 +485,7 @@ ${renderSkillsHelpFooter(caps())}
485
485
  }
486
486
  );
487
487
  program.command("review <range>").description("\uB9AC\uBDF0\uC5B4\uC5D0\uAC8C \uB118\uAE38 \uC790\uB8CC\uB97C \uC870\uB9BD\uD569\uB2C8\uB2E4 (provenance \uD3EC\uD568)").option("--json", "\uAE30\uACC4\uAC00 \uC77D\uC744 \uC218 \uC788\uB294 JSON\uC73C\uB85C \uCD9C\uB825\uD569\uB2C8\uB2E4").option("--base <ref>", "diff \uAE30\uC900 (\uAE30\uBCF8\uC740 \uC644\uB8CC \uC870\uAC74 baseline)").action(async (range, opts) => {
488
- const { runReview } = await import("./review-CGALGS5X.js");
488
+ const { runReview } = await import("./review-RT7EPECQ.js");
489
489
  await runReview(range, { json: opts.json === true, base: opts.base });
490
490
  });
491
491
  program.command("record <type>", { hidden: true }).description("\uAD6C\uC870\uD654\uB41C \uAE30\uB85D\uC744 \uB0A8\uAE41\uB2C8\uB2E4").option("--json <data>", "\uAE30\uB85D\uD560 \uB370\uC774\uD130 (JSON \uBB38\uC790\uC5F4)").option("--file <path>", "\uB370\uC774\uD130 \uD30C\uC77C \uACBD\uB85C (\uD070 \uB370\uC774\uD130\uC6A9)").option("--diff", "git diff \uB97C \uCEA1\uCC98\uD574 \uCCA8\uBD80\uD569\uB2C8\uB2E4 (blocked)").option("--workitem <id>", "\uC774 \uAE30\uB85D\uB9CC \uB2E4\uB978 \uC6CC\uD06C\uC544\uC774\uD15C\uC73C\uB85C \uB0A8\uAE41\uB2C8\uB2E4(\uAE30\uBCF8\uC740 \uD604\uC7AC \uC6CC\uD06C\uC544\uC774\uD15C)").action(
@@ -504,7 +504,7 @@ ${renderSkillsHelpFooter(caps())}
504
504
  "\uBCC0\uACBD\uB41C \uD30C\uC77C\uC5D0 \uAD00\uB828\uB41C \uD14C\uC2A4\uD2B8\uB9CC \uC2E4\uD589\uD569\uB2C8\uB2E4(relatedCmd \uD544\uC694, \uC5C6\uC73C\uBA74 \uC804\uCCB4 \uD14C\uC2A4\uD2B8\uB85C \uD3F4\uBC31)"
505
505
  ).action(
506
506
  async (opts) => {
507
- const { runVerify } = await import("./verify-7NQ3DOFY.js");
507
+ const { runVerify } = await import("./verify-34G2WAQ4.js");
508
508
  await runVerify({
509
509
  json: opts.json === true,
510
510
  bail: opts.bail === true,
@@ -8,11 +8,11 @@ import {
8
8
  gitHasCommits,
9
9
  renderText,
10
10
  runDoctor
11
- } from "./chunk-DA27NBCS.js";
11
+ } from "./chunk-R4UNIGE5.js";
12
12
  import "./chunk-FK3Q7UY2.js";
13
13
  import "./chunk-VE2GVNNS.js";
14
- import "./chunk-XWMS6Z5E.js";
15
- import "./chunk-ZEX5ZF6C.js";
14
+ import "./chunk-SFTVZFTQ.js";
15
+ import "./chunk-YW64OU6W.js";
16
16
  import "./chunk-MLTY3EE6.js";
17
17
  import "./chunk-SJG22DAK.js";
18
18
  import "./chunk-FGHILN3D.js";
@@ -9,19 +9,19 @@ import {
9
9
  runLaneRemove,
10
10
  unmergedCommitCount,
11
11
  worktreeUntracked
12
- } from "./chunk-SSSOO2GH.js";
13
- import "./chunk-AGFQC2UO.js";
12
+ } from "./chunk-R5JAYYQ6.js";
13
+ import "./chunk-5HXSUU6Y.js";
14
14
  import "./chunk-D5OINC3G.js";
15
15
  import "./chunk-EHJYX57P.js";
16
16
  import "./chunk-ZRKOZQKP.js";
17
17
  import "./chunk-IVEV5L7P.js";
18
- import "./chunk-WWZIKKHP.js";
18
+ import "./chunk-NCS2EPDP.js";
19
19
  import "./chunk-VVZOIFL4.js";
20
- import "./chunk-DA27NBCS.js";
20
+ import "./chunk-R4UNIGE5.js";
21
21
  import "./chunk-FK3Q7UY2.js";
22
22
  import "./chunk-VE2GVNNS.js";
23
- import "./chunk-XWMS6Z5E.js";
24
- import "./chunk-ZEX5ZF6C.js";
23
+ import "./chunk-SFTVZFTQ.js";
24
+ import "./chunk-YW64OU6W.js";
25
25
  import "./chunk-MLTY3EE6.js";
26
26
  import "./chunk-SJG22DAK.js";
27
27
  import "./chunk-FGHILN3D.js";
@@ -4,22 +4,22 @@ import {
4
4
  laneBranchMap,
5
5
  unmergedCommitCount,
6
6
  worktreeUntracked
7
- } from "./chunk-SSSOO2GH.js";
7
+ } from "./chunk-R5JAYYQ6.js";
8
8
  import {
9
9
  removeGitWorktree,
10
10
  worktreeDirtyTracked
11
- } from "./chunk-AGFQC2UO.js";
11
+ } from "./chunk-5HXSUU6Y.js";
12
12
  import "./chunk-D5OINC3G.js";
13
13
  import "./chunk-EHJYX57P.js";
14
14
  import "./chunk-ZRKOZQKP.js";
15
15
  import "./chunk-IVEV5L7P.js";
16
- import "./chunk-WWZIKKHP.js";
16
+ import "./chunk-NCS2EPDP.js";
17
17
  import "./chunk-VVZOIFL4.js";
18
- import "./chunk-DA27NBCS.js";
18
+ import "./chunk-R4UNIGE5.js";
19
19
  import "./chunk-FK3Q7UY2.js";
20
20
  import "./chunk-VE2GVNNS.js";
21
- import "./chunk-XWMS6Z5E.js";
22
- import "./chunk-ZEX5ZF6C.js";
21
+ import "./chunk-SFTVZFTQ.js";
22
+ import "./chunk-YW64OU6W.js";
23
23
  import {
24
24
  resolveProjectRoot
25
25
  } from "./chunk-MLTY3EE6.js";
@@ -6,15 +6,15 @@ import "./chunk-ZRKOZQKP.js";
6
6
  import "./chunk-IVEV5L7P.js";
7
7
  import {
8
8
  runVerifyChecks
9
- } from "./chunk-WWZIKKHP.js";
9
+ } from "./chunk-NCS2EPDP.js";
10
10
  import "./chunk-VVZOIFL4.js";
11
- import "./chunk-DA27NBCS.js";
11
+ import "./chunk-R4UNIGE5.js";
12
12
  import "./chunk-FK3Q7UY2.js";
13
13
  import {
14
14
  loadState
15
15
  } from "./chunk-VE2GVNNS.js";
16
- import "./chunk-XWMS6Z5E.js";
17
- import "./chunk-ZEX5ZF6C.js";
16
+ import "./chunk-SFTVZFTQ.js";
17
+ import "./chunk-YW64OU6W.js";
18
18
  import {
19
19
  requireConfig,
20
20
  run
@@ -11,13 +11,13 @@ import {
11
11
  substituteRelatedCmd,
12
12
  verifyBaselinePath,
13
13
  writeVerifyBaseline
14
- } from "./chunk-WWZIKKHP.js";
14
+ } from "./chunk-NCS2EPDP.js";
15
15
  import "./chunk-VVZOIFL4.js";
16
- import "./chunk-DA27NBCS.js";
16
+ import "./chunk-R4UNIGE5.js";
17
17
  import "./chunk-FK3Q7UY2.js";
18
18
  import "./chunk-VE2GVNNS.js";
19
- import "./chunk-XWMS6Z5E.js";
20
- import "./chunk-ZEX5ZF6C.js";
19
+ import "./chunk-SFTVZFTQ.js";
20
+ import "./chunk-YW64OU6W.js";
21
21
  import "./chunk-MLTY3EE6.js";
22
22
  import "./chunk-SJG22DAK.js";
23
23
  import "./chunk-FGHILN3D.js";
@@ -2,8 +2,8 @@ import {
2
2
  gatherVersionInputs,
3
3
  renderVersionCheck,
4
4
  runVersionCheck
5
- } from "./chunk-XWMS6Z5E.js";
6
- import "./chunk-ZEX5ZF6C.js";
5
+ } from "./chunk-SFTVZFTQ.js";
6
+ import "./chunk-YW64OU6W.js";
7
7
  import "./chunk-MLTY3EE6.js";
8
8
  import "./chunk-SJG22DAK.js";
9
9
  import "./chunk-FGHILN3D.js";
@@ -20,18 +20,18 @@ import {
20
20
  summarizeWorkitems,
21
21
  withCostAtStart,
22
22
  worktreeDirtyTracked
23
- } from "./chunk-AGFQC2UO.js";
23
+ } from "./chunk-5HXSUU6Y.js";
24
24
  import "./chunk-D5OINC3G.js";
25
25
  import "./chunk-EHJYX57P.js";
26
26
  import "./chunk-ZRKOZQKP.js";
27
27
  import "./chunk-IVEV5L7P.js";
28
- import "./chunk-WWZIKKHP.js";
28
+ import "./chunk-NCS2EPDP.js";
29
29
  import "./chunk-VVZOIFL4.js";
30
- import "./chunk-DA27NBCS.js";
30
+ import "./chunk-R4UNIGE5.js";
31
31
  import "./chunk-FK3Q7UY2.js";
32
32
  import "./chunk-VE2GVNNS.js";
33
- import "./chunk-XWMS6Z5E.js";
34
- import "./chunk-ZEX5ZF6C.js";
33
+ import "./chunk-SFTVZFTQ.js";
34
+ import "./chunk-YW64OU6W.js";
35
35
  import "./chunk-MLTY3EE6.js";
36
36
  import "./chunk-SJG22DAK.js";
37
37
  import "./chunk-FGHILN3D.js";
@@ -1,4 +1,4 @@
1
1
  {
2
- "engineVersion": "0.6.46",
2
+ "engineVersion": "0.6.47",
3
3
  "note": "~/.awl/engine 으로 복사되는 스킬·검사기·템플릿·마이그레이션. skills/ 에 awl-loop 스킬이 들어있습니다."
4
4
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-work-loop",
3
- "version": "0.6.46",
3
+ "version": "0.6.47",
4
4
  "description": "같은 실패를 두 번 하지 않는 도구. AI 에이전트가 한 일과 확인한 내용을 파일로 남깁니다.",
5
5
  "type": "module",
6
6
  "bin": {