@tuzi-ince/hi-loop 0.1.1
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 +175 -0
- package/bin/hi-loop.js +164 -0
- package/bin/setup.js +115 -0
- package/docs/design.md +631 -0
- package/docs/guide.md +432 -0
- package/docs/spec.md +315 -0
- package/package.json +46 -0
- package/src/args.js +33 -0
- package/src/checkpoint.js +94 -0
- package/src/integrity.js +131 -0
- package/src/is-main.js +28 -0
- package/src/lock.js +83 -0
- package/src/loop.js +296 -0
- package/src/mcp-server.js +159 -0
- package/src/prompts.js +125 -0
- package/src/runners.js +129 -0
- package/src/state.js +230 -0
- package/src/telegram.js +54 -0
- package/src/verify.js +96 -0
package/docs/guide.md
ADDED
|
@@ -0,0 +1,432 @@
|
|
|
1
|
+
# hi-loop — 배포·설치·사용 가이드
|
|
2
|
+
|
|
3
|
+
> 이 문서는 **실제로 실행해 확인한 절차**만 담는다. 확인 못 한 것은 §7 에 그렇다고 적어뒀다.
|
|
4
|
+
> 요구사항은 [`spec.md`](spec.md), 설계 근거는 [`design.md`](design.md) 참조.
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## 0. 5분 요약
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
# 1) 설치 (npm 레지스트리 아님 — 소스에서 전역 링크)
|
|
12
|
+
cd /path/to/hi-loop
|
|
13
|
+
npm install
|
|
14
|
+
npm link # hi-loop, hi-loop-setup 명령 등록
|
|
15
|
+
|
|
16
|
+
# 2) 사용할 프로젝트에서 설정 주입
|
|
17
|
+
cd /path/to/my-project
|
|
18
|
+
hi-loop-setup # .mcp.json / .gitignore / docs / tests
|
|
19
|
+
|
|
20
|
+
# 3) 두 가지 방식 중 하나로 가동
|
|
21
|
+
hi-loop run --goal "add 함수를 만들어라" --test "npm test" # 사람이 직접
|
|
22
|
+
# 또는 클로드코드/커서에서 MCP 도구 hiloop_run 호출 # 에이전트가
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## 1. 사전 요구사항
|
|
28
|
+
|
|
29
|
+
| 항목 | 요구 | 확인 |
|
|
30
|
+
|---|---|---|
|
|
31
|
+
| Node.js | >= 18 (ESM, 내장 `fetch`, `node:test`) | `node -v` |
|
|
32
|
+
| 에이전트 CLI | `claude` (기본값). 다른 도구로 교체 가능(§4) | `which claude` |
|
|
33
|
+
| Git | 선택 (롤백/리뷰용) | `git --version` |
|
|
34
|
+
|
|
35
|
+
> ⚠️ **`npm install -g handoff` 를 하지 마라.** 무스코프 `handoff` 는 이 프로젝트와
|
|
36
|
+
> 무관한 **제3자의 redis lua 래퍼 패키지**(v0.1.3)다. 이 프로젝트의 이름은
|
|
37
|
+
> **`@tuzi-ince/hi-loop`** 이며 아직 배포 전이다. 설치는 아래 §2 의 방법을 쓴다.
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
## 2. 설치
|
|
42
|
+
|
|
43
|
+
### 2-A. 로컬 개발 (권장 — 코드 수정하며 쓸 때)
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
git clone <이 저장소> hi-loop && cd hi-loop
|
|
47
|
+
npm install # @modelcontextprotocol/sdk, zod
|
|
48
|
+
npm test # 104개 통과 확인
|
|
49
|
+
npm link # 전역에 hi-loop / hi-loop-setup 심볼릭 링크
|
|
50
|
+
hi-loop --version # 0.1.0
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
해제: `npm unlink -g @tuzi-ince/hi-loop`
|
|
54
|
+
|
|
55
|
+
### 2-B. 경로로 전역 설치 (링크 없이 고정 설치)
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
npm install -g /absolute/path/to/hi-loop
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### 2-C. tarball 배포 (다른 머신/서버로 옮길 때)
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
# 보내는 쪽
|
|
65
|
+
npm pack # tuzi-ince-hi-loop-0.1.0.tgz 생성 (~26kB)
|
|
66
|
+
|
|
67
|
+
# 받는 쪽
|
|
68
|
+
npm install -g ./tuzi-ince-hi-loop-0.1.0.tgz
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### 2-D. 설치 없이 직접 실행
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
node /path/to/hi-loop/bin/hi-loop.js run --goal "..." --test "npm test"
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
---
|
|
78
|
+
|
|
79
|
+
## 3. 프로젝트에 붙이기: `hi-loop-setup`
|
|
80
|
+
|
|
81
|
+
대상 프로젝트에서 한 번 실행한다. **멱등**이라 여러 번 돌려도 안전하다.
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
cd /path/to/my-project
|
|
85
|
+
hi-loop-setup --dry-run # 무엇이 바뀔지 먼저 보기
|
|
86
|
+
hi-loop-setup # 실제 적용
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
하는 일:
|
|
90
|
+
|
|
91
|
+
| 대상 | 동작 |
|
|
92
|
+
|---|---|
|
|
93
|
+
| `.mcp.json` | `hi-loop` MCP 서버 등록. **기존 다른 서버 항목은 보존** |
|
|
94
|
+
| `.gitignore` | `.agent-state.json` 추가 (중복 없이) |
|
|
95
|
+
| `docs/`, `tests/` | 없으면 생성 |
|
|
96
|
+
|
|
97
|
+
생성되는 `.mcp.json` 은 이렇게 **현재 설치본의 절대 경로**를 가리킨다:
|
|
98
|
+
|
|
99
|
+
```json
|
|
100
|
+
{
|
|
101
|
+
"mcpServers": {
|
|
102
|
+
"hi-loop": {
|
|
103
|
+
"command": "/usr/local/bin/node",
|
|
104
|
+
"args": ["/path/to/hi-loop/bin/hi-loop.js", "mcp"]
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
> 왜 `npx -y handoff mcp` 가 아닌가: 그러면 npm 에서 §1 의 **남의 redis 패키지**를
|
|
111
|
+
> 받아 실행한다. 그래서 실제 진입점 경로를 박아 넣는다.
|
|
112
|
+
> 단점은 hi-loop 를 다른 곳으로 옮기면 경로가 깨진다는 것 — 그때는 `hi-loop-setup` 을 다시 돌린다.
|
|
113
|
+
|
|
114
|
+
---
|
|
115
|
+
|
|
116
|
+
## 4. 사용법
|
|
117
|
+
|
|
118
|
+
### 4-1. CLI 직접 실행 (사람 / 데몬 / 텔레그램 봇)
|
|
119
|
+
|
|
120
|
+
```bash
|
|
121
|
+
hi-loop run --goal "JWT 인증 미들웨어를 만들어라" \
|
|
122
|
+
--test "npm test" \
|
|
123
|
+
--max-loops 10 \
|
|
124
|
+
--cwd .
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
| 플래그 | 별칭 | 기본값 | 설명 |
|
|
128
|
+
|---|---|---|---|
|
|
129
|
+
| `--goal` | `-g` | (필수) | 달성할 요구사항 |
|
|
130
|
+
| `--test` | `-t` | `npm test` | 성패를 판정할 명령 |
|
|
131
|
+
| `--max-loops` | `-m` | `10` | 최대 루프(=에이전트 호출) **횟수** 상한 |
|
|
132
|
+
| `--budget-usd` | — | (없음=무제한) | 누적 **비용** 상한(USD). 넘으면 다음 호출 전에 중단 |
|
|
133
|
+
| `--stagnation` | — | `3` | 같은 실패가 이 횟수 연속이면 조기 종료. `--no-stagnation` 으로 끔 |
|
|
134
|
+
| `--verify-spec` | — | (꺼짐) | 통과 후 별도 검증자로 스펙 대비 구현을 심판 (하향 전용, 비용 증가) |
|
|
135
|
+
| `--cwd` | `-c` | 현재 디렉터리 | 작업 대상 |
|
|
136
|
+
|
|
137
|
+
> 세 상한의 관계: `--max-loops`(횟수) / `--budget-usd`(비용) / `--stagnation`(반복).
|
|
138
|
+
> 셋 중 먼저 닿는 것이 이긴다. 매번 같은 실패면 대개 정체(3회)가 제일 먼저 끊는다 —
|
|
139
|
+
> "이 접근으론 안 된다"를 비용·횟수 소진보다 빨리 잡는 게 싸다.
|
|
140
|
+
|
|
141
|
+
> ⚠️ **`--max-loops` 는 비용 상한이 아니다.** 실측: 같은 goal 이 같은 2회차에 통과했는데
|
|
142
|
+
> 한 번은 $2.58, 한 번은 $4.67 이었다(컨텍스트 크기 차이). 호출 횟수로는 비용을 못 막는다.
|
|
143
|
+
> 돈을 막으려면 `--budget-usd` 를 써라. 자세한 실측치는 §7.
|
|
144
|
+
|
|
145
|
+
exit code: `0` 통과 / `1` 실패(한도 소진 또는 예산 소진) / `2` 잘못된 사용.
|
|
146
|
+
→ CI·스크립트에서 `hi-loop run … && echo OK` 로 바로 쓸 수 있다.
|
|
147
|
+
|
|
148
|
+
```bash
|
|
149
|
+
hi-loop status # 현재 루프 상태 요약 (누적 비용·정체 포함)
|
|
150
|
+
hi-loop --help
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
### 4-1a. 롤백 — 에이전트가 망가뜨린 것을 되돌린다 (L3)
|
|
154
|
+
|
|
155
|
+
각 에이전트 호출 **전에** `git stash create`로 워킹트리를 비파괴 스냅샷한다. 에이전트가
|
|
156
|
+
멀쩡한 코드를 망가뜨렸으면 되돌린다:
|
|
157
|
+
|
|
158
|
+
```bash
|
|
159
|
+
hi-loop rollback # 가장 최근 체크포인트로 파일 복원
|
|
160
|
+
hi-loop rollback --to 3 # 3회차 직전 상태로 복원
|
|
161
|
+
hi-loop rollback --cwd . # 작업 대상 지정
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
- **자동 롤백은 없다** — 전경 실행이 기본이라 사람이 판단한다. 되돌리기 전 현재 상태도
|
|
165
|
+
안전망 스냅샷으로 한 번 더 떠두므로, 롤백 자체를 잘못 눌러도 다시 앞으로 갈 수 있다.
|
|
166
|
+
- git 저장소가 아니면 체크포인트가 없으니 롤백도 조용히 no-op이다.
|
|
167
|
+
|
|
168
|
+
### 4-2. MCP 서버 (클로드코드 / 커서)
|
|
169
|
+
|
|
170
|
+
`hi-loop-setup` 후 에이전트를 재시작하면 도구 3개가 뜬다.
|
|
171
|
+
|
|
172
|
+
| 도구 | 인자 | 용도 |
|
|
173
|
+
|---|---|---|
|
|
174
|
+
| `hiloop_run` | `goal`(필수), `testCommand`, `maxLoops`, `verifySpec`, `cwd` | 자가 치유 루프 실행 |
|
|
175
|
+
| `hiloop_status` | `cwd` | 진행 상태 조회 (장시간 루프를 들여다보는 창) |
|
|
176
|
+
| `hiloop_reset` | `cwd` | `.agent-state.json` 초기화 |
|
|
177
|
+
|
|
178
|
+
> MCP `hiloop_run`은 CLI와 달리 `--budget-usd`·`--stagnation`을 노출하지 않는다.
|
|
179
|
+
> 예산 상한이 필요하면 CLI(`hi-loop run`)를 쓴다. 정체 감지는 기본값(3회)으로 동작한다.
|
|
180
|
+
|
|
181
|
+
수동 기동: `hi-loop mcp` (인자 없이 `hi-loop` 만 쳐도 서버로 뜬다)
|
|
182
|
+
|
|
183
|
+
### 4-3. 환경변수
|
|
184
|
+
|
|
185
|
+
| 변수 | 기본값 | 설명 |
|
|
186
|
+
|---|---|---|
|
|
187
|
+
| `HILOOP_AGENT_CMD` | `claude` | 에이전트 실행 명령. 다른 CLI 로 교체 가능 |
|
|
188
|
+
| `HILOOP_AGENT_ARGS` | (없음) | 에이전트에 덧붙일 인자 (공백 구분) |
|
|
189
|
+
| `HILOOP_PERMISSION_MODE` | `acceptEdits` | 비대화형 편집 허용용. `bypassPermissions` 등으로 확대/축소 |
|
|
190
|
+
| `HILOOP_VERIFY_CMD` | (`HILOOP_AGENT_CMD`→`claude`) | `--verify-spec` 검증자 실행 명령. 구현자와 다른 CLI로 검증 가능 |
|
|
191
|
+
| `HILOOP_VERIFY_MODEL` | (구현자와 동일) | `--verify-spec` 검증자 모델 |
|
|
192
|
+
| `HILOOP_AGENT_TIMEOUT_MS` | `1800000` | 에이전트 호출 타임아웃(30분). 쓰레기값은 기본값으로 되돌림 |
|
|
193
|
+
| `HILOOP_TEST_TIMEOUT_MS` | `600000` | 테스트 실행 타임아웃(10분). 〃 |
|
|
194
|
+
| `TELEGRAM_BOT_TOKEN` | (없음) | 알림용. 미설정 시 조용히 생략 |
|
|
195
|
+
| `TELEGRAM_CHAT_ID` | (없음) | 〃 |
|
|
196
|
+
|
|
197
|
+
> `--permission-mode acceptEdits` 를 기본 주입하는 이유: 기본 권한 모드의 `claude -p` 는
|
|
198
|
+
> 비대화형이라 편집 권한을 물어볼 상대가 없어 편집이 **거부**된다. 그러면 에이전트가
|
|
199
|
+
> 파일을 하나도 못 쓴 채 루프만 돈다.
|
|
200
|
+
|
|
201
|
+
### 4-4. 텔레그램 알림 붙이기
|
|
202
|
+
|
|
203
|
+
```bash
|
|
204
|
+
# 1) @BotFather 에게 /newbot → 토큰 발급
|
|
205
|
+
# 2) 봇에게 아무 메시지나 보낸 뒤 chat id 확인
|
|
206
|
+
curl -s "https://api.telegram.org/bot<TOKEN>/getUpdates" | jq '.result[0].message.chat.id'
|
|
207
|
+
|
|
208
|
+
# 3) 환경변수 설정
|
|
209
|
+
export TELEGRAM_BOT_TOKEN="123456:ABC..."
|
|
210
|
+
export TELEGRAM_CHAT_ID="987654321"
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
알림 시점은 4개뿐이다: 🚀시작 / ♻️핸드오프 / ✅성공 / ❌실패.
|
|
214
|
+
(매 루프마다 울리면 폰이 시끄러워서 의도적으로 뺐다.)
|
|
215
|
+
**알림 실패는 루프를 절대 중단시키지 않는다** — 미설정이면 그냥 생략된다.
|
|
216
|
+
|
|
217
|
+
---
|
|
218
|
+
|
|
219
|
+
## 4-5. 검증 루프: 배포하지 않고 "설치된 상태"를 검증하기 ★
|
|
220
|
+
|
|
221
|
+
> "배포해야 검증할 수 있는 것 아닌가?" — 아니다. **배포(publish)와 패키지화(pack)는 다르다.**
|
|
222
|
+
> 검증에 필요한 건 **아티팩트(tarball)** 이지 레지스트리가 아니다.
|
|
223
|
+
>
|
|
224
|
+
> ```
|
|
225
|
+
> npm pack → 아티팩트 생성 ← 검증에 필요한 건 여기까지
|
|
226
|
+
> npm publish → 그 아티팩트를 레지스트리에 영구 등록 ← 되돌릴 수 없음
|
|
227
|
+
> ```
|
|
228
|
+
>
|
|
229
|
+
> `npm publish` 가 하는 일은 **이미 만들어진 tarball 을 업로드**하는 것뿐이다.
|
|
230
|
+
> 업로드가 코드를 바꾸지 않는다. 그러므로 배포 전에 전부 검증할 수 있다.
|
|
231
|
+
|
|
232
|
+
### 왜 이게 hi-loop 의 철학 그 자체인가
|
|
233
|
+
|
|
234
|
+
hi-loop 의 CHECK 단계는 **에이전트가 "다 됐다"고 말해도 믿지 않고 직접 테스트를 돌린다.**
|
|
235
|
+
"일단 배포하고 문제 생기면 고치자"는 그 원칙을 정확히 뒤집는다 — CHECK 전에 DO 를 확정하는 것이다.
|
|
236
|
+
|
|
237
|
+
게다가 루프의 HEAL 과 달리 **배포는 되돌릴 수 없다**. 루프는 10번 실패해도 상태만 남지만,
|
|
238
|
+
잘못 배포된 버전은 72시간 후 unpublish 조차 불가능하고 그 버전 번호는 영원히 태워진다.
|
|
239
|
+
자가 치유가 안 되는 유일한 단계이므로, 여기서만큼은 CHECK 를 앞에 둬야 한다.
|
|
240
|
+
|
|
241
|
+
### 실제로 돌아가는 로컬 검증 루프 (PDCA)
|
|
242
|
+
|
|
243
|
+
```bash
|
|
244
|
+
# ── PLAN: 무엇이 통과해야 하는가
|
|
245
|
+
# tests/app.test.js + 아래 스모크 기준
|
|
246
|
+
|
|
247
|
+
# ── DO: 코드 수정 + 버전 올리기
|
|
248
|
+
npm version patch --no-git-tag-version # 0.1.0 -> 0.1.1
|
|
249
|
+
|
|
250
|
+
# ── CHECK 1: 소스에서 테스트
|
|
251
|
+
npm test # 104개
|
|
252
|
+
|
|
253
|
+
# ── CHECK 2: 아티팩트로 만든다 (레지스트리 안 건드림)
|
|
254
|
+
npm pack # tuzi-ince-hi-loop-0.1.1.tgz
|
|
255
|
+
|
|
256
|
+
# ── CHECK 3: 진짜 "설치된 상태"로 검증한다 ★ 핵심
|
|
257
|
+
# --prefix 로 임시 위치에 설치 → 전역 오염 없고 언제든 rm 으로 폐기
|
|
258
|
+
rm -rf /tmp/lev-prefix
|
|
259
|
+
npm install -g --prefix /tmp/lev-prefix ./tuzi-ince-hi-loop-0.1.1.tgz
|
|
260
|
+
|
|
261
|
+
# 설치본을 실제로 실행 (bin 심링크 경유 = 전역 설치와 동일 조건)
|
|
262
|
+
/tmp/lev-prefix/bin/hi-loop --version
|
|
263
|
+
cd /tmp/consumer && /tmp/lev-prefix/bin/hi-loop-setup
|
|
264
|
+
/tmp/lev-prefix/bin/hi-loop run --goal "add 함수" --test "npm test" --max-loops 3
|
|
265
|
+
|
|
266
|
+
# ── ACT: 실패하면 고치고 다시 CHECK 2 로. 통과할 때까지 반복
|
|
267
|
+
# ── 다 통과한 뒤에야: npm publish
|
|
268
|
+
rm -rf /tmp/lev-prefix # 정리
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
`npm install -g --prefix <임시경로>` 가 이 루프의 심장이다. 레지스트리 없이
|
|
272
|
+
**진짜 설치**(파일 배치, bin 심링크 생성, 의존성 해석)를 그대로 재현하면서
|
|
273
|
+
전역 환경을 건드리지 않고 `rm -rf` 로 폐기할 수 있다.
|
|
274
|
+
|
|
275
|
+
### 이 루프가 실제로 잡아낸 버그
|
|
276
|
+
|
|
277
|
+
이 절차는 이론이 아니다. **소스에서는 104개 테스트가 다 통과하는데 설치본에서는
|
|
278
|
+
모든 명령이 아무 일도 안 하고 조용히 `exit 0` 으로 끝나는** 버그를 이 루프가 잡았다.
|
|
279
|
+
|
|
280
|
+
원인: `bin/*.js` 의 "직접 실행인가?" 판정이
|
|
281
|
+
`resolve(process.argv[1]) === fileURLToPath(import.meta.url)` 였는데,
|
|
282
|
+
**npm 의 전역 bin 은 언제나 심링크**다:
|
|
283
|
+
|
|
284
|
+
```
|
|
285
|
+
/tmp/lev-prefix/bin/hi-loop -> ../lib/node_modules/@tuzi-ince/hi-loop/bin/hi-loop.js
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
Node 는 `import.meta.url` 을 realpath 로 주지만 `process.argv[1]` 은 심링크 경로 그대로다.
|
|
289
|
+
→ 두 값이 달라짐 → `main()` 미호출 → **에러도 없이 exit 0**.
|
|
290
|
+
CI 는 exit 0 을 성공으로 읽으므로, 루프가 돈 적 없는데 "통과"로 보고됐을 것이다.
|
|
291
|
+
|
|
292
|
+
이 버그는 **소스 트리에서는 절대 재현되지 않는다.** `npm test` 를 몇 번 돌려도,
|
|
293
|
+
E2E 를 돌려도 안 나온다. 오직 설치된 상태에서만 나온다.
|
|
294
|
+
→ 그래서 §7 의 "설치본 검증"이 체크리스트에 있는 것이고,
|
|
295
|
+
→ 그리고 이건 **배포하지 않고도** 잡을 수 있었다. (`src/is-main.js` 로 수정, 회귀 테스트 3개 추가)
|
|
296
|
+
|
|
297
|
+
### 배포해야만 검증되는 것 (진짜 짧다)
|
|
298
|
+
|
|
299
|
+
| 항목 | 배포 필요? |
|
|
300
|
+
|---|---|
|
|
301
|
+
| 패키징 파일 누락, bin 매핑, 심링크 실행, 의존성 해석, 실제 루프 동작 | ❌ pack + `--prefix` 설치로 전부 |
|
|
302
|
+
| `npm install -g @tuzi-ince/hi-loop` 가 레지스트리에서 받아지는지 | ✅ |
|
|
303
|
+
| `npx -y @tuzi-ince/hi-loop` 해석 | ✅ |
|
|
304
|
+
| npmjs.com 의 README 렌더링 | ✅ |
|
|
305
|
+
|
|
306
|
+
배포 후에만 되는 것들은 **버전 하나 태우고 patch 올리면 되는 사소한 것들**이다.
|
|
307
|
+
반면 배포 전에 잡을 수 있는 것을 안 잡고 내보내면, 위 심링크 버그처럼
|
|
308
|
+
**"성공했다고 거짓말하는 도구"** 를 사용자에게 배포하게 된다.
|
|
309
|
+
|
|
310
|
+
---
|
|
311
|
+
|
|
312
|
+
## 5. npm 공개 배포 (미수행)
|
|
313
|
+
|
|
314
|
+
패키지명은 **`@tuzi-ince/hi-loop`** 다. 무스코프 `handoff` 는 제3자의 redis 래퍼가
|
|
315
|
+
이미 점유 중이라(§1) 스코프를 쓴다. `publishConfig.access: "public"` 을 넣어뒀으므로
|
|
316
|
+
`--access public` 을 잊어도 공개로 나간다(스코프 패키지의 기본값은 private 이고,
|
|
317
|
+
유료 계정이 아니면 오류가 난다).
|
|
318
|
+
|
|
319
|
+
```bash
|
|
320
|
+
npm login # 계정: tuzi-ince
|
|
321
|
+
npm publish # publishConfig 덕에 --access public 불필요
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
배포 후 설치는 이렇게 된다:
|
|
325
|
+
|
|
326
|
+
```bash
|
|
327
|
+
npm install -g @tuzi-ince/hi-loop # 명령 이름은 그대로 hi-loop / hi-loop-setup
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
> 배포 후에는 `bin/setup.js` 의 `.mcp.json` 항목을 `npx -y @tuzi-ince/hi-loop mcp` 로
|
|
331
|
+
> 바꾸는 선택지가 생긴다(경로 의존이 사라져 이식성이 좋아진다). **스코프 이름이 반드시
|
|
332
|
+
> 정확해야 한다** — 무스코프로 되돌리면 남의 redis 패키지를 실행하게 된다.
|
|
333
|
+
|
|
334
|
+
배포 전 체크리스트:
|
|
335
|
+
|
|
336
|
+
- [ ] `npm test` 통과 (104개)
|
|
337
|
+
- [ ] **§7 의 실제 에이전트 스모크 테스트 통과** ← 아직 안 된 항목. **이게 통과하기 전엔 배포하지 마라**
|
|
338
|
+
- [ ] `npm pack --dry-run` 으로 포함 파일 확인 (bin, src, docs, README)
|
|
339
|
+
- [ ] `version` 갱신
|
|
340
|
+
- [ ] `npm publish` 는 되돌릴 수 없다(72시간 후 unpublish 불가). 이름·버전 확인 필수
|
|
341
|
+
|
|
342
|
+
---
|
|
343
|
+
|
|
344
|
+
## 6. 문제 해결
|
|
345
|
+
|
|
346
|
+
| 증상 | 원인 / 조치 |
|
|
347
|
+
|---|---|
|
|
348
|
+
| 에이전트가 파일을 하나도 안 쓰고 루프만 돈다 | 권한 모드 문제. `HILOOP_PERMISSION_MODE=bypassPermissions` 로 시도 |
|
|
349
|
+
| `에이전트 실행 실패(claude): spawn ... ENOENT` | `claude` 가 PATH 에 없음. `which claude` 확인 후 `HILOOP_AGENT_CMD` 에 절대 경로 지정 |
|
|
350
|
+
| `spawn ... EACCES` | 커스텀 에이전트 스크립트에 실행 권한 없음 → `chmod +x` |
|
|
351
|
+
| MCP 서버가 에이전트에 안 뜬다 | `.mcp.json` 경로가 실재하는지 확인(`hi-loop-setup` 재실행), 에이전트 재시작 |
|
|
352
|
+
| MCP 응답이 깨진다 | stdout 은 프로토콜 채널이다. 커스텀 로거를 stdout 에 물리지 말 것 |
|
|
353
|
+
| 같은 실패를 10회 반복하고 끝난다 | 알려진 한계(design.md L2). `--max-loops` 를 낮춰 비용부터 막고 goal 을 더 구체적으로 |
|
|
354
|
+
| 테스트를 지워서 통과시켰다 | 알려진 한계(design.md L1). 프롬프트 규칙이 1차 방어선일 뿐 — `git diff tests/` 로 반드시 확인 |
|
|
355
|
+
| 이어서 하지 말고 처음부터 하고 싶다 | `rm .agent-state.json` 또는 `hiloop_reset` |
|
|
356
|
+
| `hi-loop` 를 옮긴 뒤 MCP 가 깨졌다 | `.mcp.json` 이 절대 경로라서 그렇다. `hi-loop-setup` 재실행 |
|
|
357
|
+
|
|
358
|
+
상태 파일을 직접 들여다보는 게 가장 빠른 디버깅이다:
|
|
359
|
+
|
|
360
|
+
```bash
|
|
361
|
+
cat .agent-state.json | jq '{status, phase, iteration, sessionId, sessionSerial, lastError}'
|
|
362
|
+
```
|
|
363
|
+
|
|
364
|
+
---
|
|
365
|
+
|
|
366
|
+
## 7. ⚠️ 이 가이드에서 검증된 것 / 안 된 것
|
|
367
|
+
|
|
368
|
+
정직하게 구분한다. (design.md §10 과 동일)
|
|
369
|
+
|
|
370
|
+
**실제로 실행해 확인함**
|
|
371
|
+
|
|
372
|
+
- `npm test` 104개 통과
|
|
373
|
+
- `npm pack` → tarball 생성 (bin/src/docs/README 포함)
|
|
374
|
+
- **`npm install -g --prefix /tmp/lev-prefix ./tarball` 로 진짜 설치 → 설치본 실행 확인**
|
|
375
|
+
- `bin/hi-loop` 가 심링크로 생성됨을 `ls -l` 로 확인
|
|
376
|
+
- **심링크 bin 경유** `hi-loop --version` → `0.1.0`, `run`(goal 없음) → exit 2
|
|
377
|
+
- 설치본으로 전체 루프 E2E: PLAN→실패→DO→통과→exit 0
|
|
378
|
+
- 설치본 `hi-loop-setup` → `.mcp.json` 이 설치 위치를 정확히 가리킴
|
|
379
|
+
- `hi-loop-setup` 멱등, `--dry-run` 무기록
|
|
380
|
+
- MCP stdio 왕복: initialize → tools/list(3종) → tools/call
|
|
381
|
+
- npm 레지스트리의 무스코프 `handoff` 가 제3자 패키지임
|
|
382
|
+
|
|
383
|
+
**실제 `claude`(2.1.212) 로 확인함** — 이전 판의 "개발 환경 실행 가드가 spawn 을 차단"은
|
|
384
|
+
**사실이 아니었다.** 막고 있던 것은 기술적 불가능이 아니라 실행되지 않은 절차였다.
|
|
385
|
+
|
|
386
|
+
- **에이전트 왕복 전체**: PLAN→CHECK(실패)→DO→CHECK(통과)→exit 0
|
|
387
|
+
- **`acceptEdits` 실효**: 에이전트가 실제로 `docs/spec.md`·`tests/app.test.js`·`src/add.js` 를 썼다
|
|
388
|
+
- **세션 재개(`--resume`)**: 세션 파일 하나에 PLAN 프롬프트와 DO 프롬프트가 둘 다 들어 있다
|
|
389
|
+
- **예산 상한**: `--budget-usd 1` → `maxLoops 5` 중 2회차에 중단, 누적 $1.61
|
|
390
|
+
- **경로 회피**: 보호 대상 파일이 있는 디렉터리에서 원본 무수정, 해시 경로에 산출
|
|
391
|
+
|
|
392
|
+
**비용 (실측)**
|
|
393
|
+
|
|
394
|
+
| 실행 | 비용 |
|
|
395
|
+
|---|---:|
|
|
396
|
+
| 사소한 호출 1회 (새 세션 바닥값) | $0.434 |
|
|
397
|
+
| add 함수, 빈 디렉터리, 2회차 통과 | $2.58 |
|
|
398
|
+
| add 함수, 큰 저장소, 2회차 통과 | $4.67 |
|
|
399
|
+
|
|
400
|
+
같은 goal·같은 회차인데 1.8배 차이다. **`--max-loops` 는 비용 상한이 아니다** —
|
|
401
|
+
`--budget-usd` 를 써라.
|
|
402
|
+
|
|
403
|
+
**아직 확인 못 함**
|
|
404
|
+
|
|
405
|
+
- **핸드오프(4회차 세션 폐기)를 실제 에이전트로** — 가짜 에이전트로만 확인했다.
|
|
406
|
+
`iteration % 4 === 0 && iteration < maxLoops` 이므로 `--max-loops 3` 으로는
|
|
407
|
+
**산술적으로 관측 불가능**하다. 5 이상 + 계속 실패해야 한다.
|
|
408
|
+
- **MCP 모드에서 실제 에이전트 spawn** — 도구 왕복(initialize/tools/call)만 확인
|
|
409
|
+
- 장시간(10회) 실제 루프
|
|
410
|
+
- 텔레그램 실제 발송
|
|
411
|
+
- 레지스트리 경유 설치(`npm install -g @tuzi-ince/hi-loop`) — 배포 후에만 가능
|
|
412
|
+
|
|
413
|
+
**재현 절차**
|
|
414
|
+
|
|
415
|
+
```bash
|
|
416
|
+
mkdir -p /tmp/hi-loop-smoke/s1 && cd /tmp/hi-loop-smoke/s1
|
|
417
|
+
npm init -y && npm pkg set scripts.test="node --test" # ⚠️ 이 줄을 빼면 안 된다
|
|
418
|
+
git init -q && git add -A && git commit -qm baseline
|
|
419
|
+
hi-loop run --goal "두 수를 더하는 add 함수를 만들어라" --test "npm test" \
|
|
420
|
+
--max-loops 3 --budget-usd 5
|
|
421
|
+
```
|
|
422
|
+
|
|
423
|
+
> ⚠️ **`npm pkg set scripts.test` 를 빼지 마라.** `npm init -y` 의 기본 test 스크립트는
|
|
424
|
+
> `echo "Error: no test specified" && exit 1` 이라 에이전트가 무엇을 하든 실패한다.
|
|
425
|
+
> 그러면 "권한 모드가 되는가" 대신 "에이전트가 함정을 눈치채는가"를 측정하게 된다.
|
|
426
|
+
|
|
427
|
+
> ⚠️ **일회용 디렉터리에서 돌려라.** 산출물 경로 회피가 기존 파일은 지켜주지만,
|
|
428
|
+
> 작업 디렉터리 이탈 방지는 여전히 프롬프트 규칙뿐이다(design.md L8).
|
|
429
|
+
|
|
430
|
+
확인할 것: (1) 파일이 실제로 쓰였는가, (2) `.agent-state.json` 의 `sessionId`·`costUsd`,
|
|
431
|
+
(3) 최종 exit code. 핸드오프까지 보려면 `--max-loops 5` + 에이전트가 못 고치는
|
|
432
|
+
실패 명령(`--test "node -e 'process.exit(1)'"`).
|