agent-work-loop 0.6.22 → 0.6.23
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 +2 -2
- package/dist/{chunk-FBEUJR2P.js → chunk-46HZN6UB.js} +1 -1
- package/dist/{chunk-TKPHC32G.js → chunk-C7BR2DCS.js} +1 -1
- package/dist/{chunk-X5LMP5J7.js → chunk-DP4O5ME2.js} +1 -1
- package/dist/{chunk-C7TN3LM3.js → chunk-G5LAJ5TV.js} +8 -3
- package/dist/{chunk-ZLTOL3D3.js → chunk-IMB46O6S.js} +1 -1
- package/dist/{chunk-CCMG377E.js → chunk-IXMAFR4Y.js} +2 -2
- package/dist/{chunk-O7GRZZPJ.js → chunk-QE2CLNBG.js} +1 -1
- package/dist/{chunk-VU6IPRRM.js → chunk-YTAHVR4P.js} +1 -1
- package/dist/{chunk-LMWAVN7B.js → chunk-ZE6HXOYG.js} +4 -4
- package/dist/cli.js +25 -26
- package/dist/{doctor-BU6HWXE4.js → doctor-SSKNLPGH.js} +3 -3
- package/dist/{evolve-NNQX2A43.js → evolve-QPD7TWGO.js} +1 -1
- package/dist/{gotchas-CW4KZDEF.js → gotchas-MCA5Y76R.js} +1 -1
- package/dist/{hold-recheck-SLI7NDLU.js → hold-recheck-WN5EG7HD.js} +9 -9
- package/dist/{lane-MIVLTDEU.js → lane-DAZISODH.js} +8 -8
- package/dist/{review-NTZ3HY3N.js → review-ZTHDJ47V.js} +6 -6
- package/dist/{rules-4VDP5LZW.js → rules-R2UZPIVW.js} +2 -2
- package/dist/{status-I3MQOCQM.js → status-L6U5KO6T.js} +9 -9
- package/dist/{uninstall-MOHJDMQH.js → uninstall-5DFEOFL5.js} +8 -8
- package/dist/{verify-6YF5FXWM.js → verify-L7ARTK42.js} +4 -4
- package/dist/{version-check-G27JYMTZ.js → version-check-LKGU2DNF.js} +2 -2
- package/dist/{work-6MMIQMUC.js → work-KEPTGZ6H.js} +7 -7
- package/engine/skills/claude/awl-pipeline/SKILL.md +6 -0
- package/engine/version.json +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
`agent-work-loop`(명령어: `awl`)은 AI 에이전트가 같은 실패를 두 번 반복하지 않도록 돕는 도구입니다. 에이전트가 작업하며 남긴 기록, 검증 결과, 완료 조건, 규칙, 교훈, 막힘을 파일로 관리합니다.
|
|
4
4
|
|
|
5
|
-
이 README는 **실용
|
|
5
|
+
이 README는 **실용 문서**입니다. 설치부터 첫 루프까지, 손으로 따라 할 수 있는 순서만 다룹니다. "왜 이렇게 만들었는가"(하네스 개념, 게이트 위치, narrative 실증 사례)는 [`docs/presentation/storyline.md`](docs/presentation/storyline.md)에 따로 정리했습니다. 명령어 하나하나의 자세한 사용법은 [`docs/presentation/commands.md`](docs/presentation/commands.md)를 참고하세요.
|
|
6
6
|
|
|
7
7
|
**awl 자체는 판단하지 않습니다.** LLM을 호출하지 않고, 파일과 상태만 결정적으로 다룹니다. 무엇을 배우고 어떤 규칙을 세울지는 이미 설치된 에이전트(Claude Code, Codex)가 스킬로 판단합니다.
|
|
8
8
|
|
|
9
|
-
크로스 환경을 처음부터 전제로 합니다. macOS와 Windows, Claude Code와 Codex를 모두 지원하는 것을 목표로 합니다(Windows는 아직 macOS만큼 검증되지
|
|
9
|
+
크로스 환경을 처음부터 전제로 합니다. macOS와 Windows, Claude Code와 Codex를 모두 지원하는 것을 목표로 합니다(Windows는 아직 macOS만큼 검증되지 않았습니다. [알려진 위험](docs/decisions.md)을 참고하세요).
|
|
10
10
|
|
|
11
11
|
---
|
|
12
12
|
|
|
@@ -267,10 +267,15 @@ function collectEvolve(project, workitem, state, scope) {
|
|
|
267
267
|
function writeGeneration(project, workitem, metrics, at, extra) {
|
|
268
268
|
const dir = generationsDir(project);
|
|
269
269
|
fs.mkdirSync(dir, { recursive: true });
|
|
270
|
-
const
|
|
270
|
+
const stamp = at.replace(/[:.]/g, "-");
|
|
271
|
+
const wi = workitem?.trim() ? workitem : "unknown";
|
|
272
|
+
const name = `${stamp}-${wi}.json`;
|
|
271
273
|
const file = path.join(dir, name);
|
|
272
|
-
fs.writeFileSync(
|
|
273
|
-
|
|
274
|
+
fs.writeFileSync(
|
|
275
|
+
file,
|
|
276
|
+
`${JSON.stringify({ workitem: wi, at, ...metrics, ...extra }, null, 2)}
|
|
277
|
+
`
|
|
278
|
+
);
|
|
274
279
|
return file;
|
|
275
280
|
}
|
|
276
281
|
function recordGotcha(input, at) {
|
|
@@ -7,16 +7,16 @@ import {
|
|
|
7
7
|
isCheckPassed,
|
|
8
8
|
runVerifyChecks,
|
|
9
9
|
writeVerifyBaseline
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-QE2CLNBG.js";
|
|
11
11
|
import {
|
|
12
12
|
gitBranch
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-IXMAFR4Y.js";
|
|
14
14
|
import {
|
|
15
15
|
parseRuleFile
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-IMB46O6S.js";
|
|
17
17
|
import {
|
|
18
18
|
nextGotchaId
|
|
19
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-G5LAJ5TV.js";
|
|
20
20
|
import {
|
|
21
21
|
loadState,
|
|
22
22
|
migrateState,
|
package/dist/cli.js
CHANGED
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
computeUpdateAvailable,
|
|
4
4
|
readCachedLatestVersion,
|
|
5
5
|
version
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-YTAHVR4P.js";
|
|
7
7
|
import {
|
|
8
8
|
caps,
|
|
9
9
|
gradient,
|
|
@@ -18,9 +18,8 @@ import {
|
|
|
18
18
|
import { Command } from "commander";
|
|
19
19
|
var BANNER = `Agent Work Loop
|
|
20
20
|
|
|
21
|
-
\uAC19\uC740 \uC2E4\uD328\uB97C \uB450 \uBC88 \uD558\uC9C0 \uC54A\
|
|
22
|
-
|
|
23
|
-
\uD310\uB2E8\uC740 Claude Code \uB098 Codex \uAC00 \uD569\uB2C8\uB2E4.
|
|
21
|
+
\uAC19\uC740 \uC2E4\uD328\uB97C \uB450 \uBC88 \uD558\uC9C0 \uC54A\uB294 \uB3C4\uAD6C\uC785\uB2C8\uB2E4.
|
|
22
|
+
\uD310\uB2E8\uC740 Claude Code\uB098 Codex\uAC00 \uD558\uACE0, awl\uC740 \uD30C\uC77C\uACFC \uC0C1\uD0DC\uB9CC \uAD00\uB9AC\uD569\uB2C8\uB2E4.
|
|
24
23
|
|
|
25
24
|
\uC2DC\uC791\uD558\uAE30:
|
|
26
25
|
1. awl init \uC774 \uD504\uB85C\uC81D\uD2B8\uB97C \uC124\uC815\uD569\uB2C8\uB2E4
|
|
@@ -123,7 +122,7 @@ function buildProgram() {
|
|
|
123
122
|
"--archive",
|
|
124
123
|
"(--pipeline\uACFC \uD568\uAED8) \uC720\uC608 \uAE30\uAC04(3\uC77C) \uC9C0\uB09C \uC644\uB8CC workitem\uC744 .tasks/archive/ \uB85C \uBCF4\uAD00\uD569\uB2C8\uB2E4"
|
|
125
124
|
).action(async (opts) => {
|
|
126
|
-
const { runStatus } = await import("./status-
|
|
125
|
+
const { runStatus } = await import("./status-L6U5KO6T.js");
|
|
127
126
|
await runStatus({
|
|
128
127
|
json: opts.json === true,
|
|
129
128
|
pipeline: opts.pipeline === true,
|
|
@@ -135,11 +134,11 @@ function buildProgram() {
|
|
|
135
134
|
await runBrief({ today: opts.today === true, date: opts.date, json: opts.json === true });
|
|
136
135
|
});
|
|
137
136
|
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) => {
|
|
138
|
-
const { runDoctor } = await import("./doctor-
|
|
137
|
+
const { runDoctor } = await import("./doctor-SSKNLPGH.js");
|
|
139
138
|
await runDoctor({ json: opts.json === true });
|
|
140
139
|
});
|
|
141
140
|
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) => {
|
|
142
|
-
const { runVersionCheck } = await import("./version-check-
|
|
141
|
+
const { runVersionCheck } = await import("./version-check-LKGU2DNF.js");
|
|
143
142
|
await runVersionCheck({ json: opts.json === true });
|
|
144
143
|
});
|
|
145
144
|
program.command("update").description("\uC124\uCE58\uB41C \uC5D4\uC9C4(~/.awl/engine)\uC744 \uAC31\uC2E0\uD569\uB2C8\uB2E4").action(async () => {
|
|
@@ -148,7 +147,7 @@ function buildProgram() {
|
|
|
148
147
|
});
|
|
149
148
|
program.command("uninstall").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(
|
|
150
149
|
async (opts) => {
|
|
151
|
-
const { runUninstall } = await import("./uninstall-
|
|
150
|
+
const { runUninstall } = await import("./uninstall-5DFEOFL5.js");
|
|
152
151
|
await runUninstall({
|
|
153
152
|
yes: opts.yes === true,
|
|
154
153
|
project: opts.project === true,
|
|
@@ -171,11 +170,11 @@ function buildProgram() {
|
|
|
171
170
|
);
|
|
172
171
|
const work = program.command("work").description("\uC774 \uD504\uB85C\uC81D\uD2B8\uC758 \uC6CC\uD06C\uC544\uC774\uD15C\uC744 \uAD00\uB9AC\uD569\uB2C8\uB2E4");
|
|
173
172
|
work.option("--json", "\uAE30\uACC4\uAC00 \uC77D\uC744 \uC218 \uC788\uB294 JSON\uC73C\uB85C \uCD9C\uB825\uD569\uB2C8\uB2E4").action(async (opts) => {
|
|
174
|
-
const { runWorkList } = await import("./work-
|
|
173
|
+
const { runWorkList } = await import("./work-KEPTGZ6H.js");
|
|
175
174
|
runWorkList({ json: opts.json === true });
|
|
176
175
|
});
|
|
177
176
|
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) => {
|
|
178
|
-
const { runWorkList } = await import("./work-
|
|
177
|
+
const { runWorkList } = await import("./work-KEPTGZ6H.js");
|
|
179
178
|
runWorkList({ json: opts.json === true });
|
|
180
179
|
});
|
|
181
180
|
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(
|
|
@@ -183,7 +182,7 @@ function buildProgram() {
|
|
|
183
182
|
"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)"
|
|
184
183
|
).option("--experiment <json>", '\uC2E4\uD5D8 \uCF00\uC774\uC2A4 \uBA54\uD0C0 JSON (\uC608: {"model":"lite","mode":"loop"})').action(
|
|
185
184
|
async (id, description, opts) => {
|
|
186
|
-
const { runWorkNew } = await import("./work-
|
|
185
|
+
const { runWorkNew } = await import("./work-KEPTGZ6H.js");
|
|
187
186
|
const parsedExp = parseExperimentOption(opts.experiment);
|
|
188
187
|
if (!parsedExp.ok) {
|
|
189
188
|
process.stderr.write(`
|
|
@@ -195,34 +194,34 @@ function buildProgram() {
|
|
|
195
194
|
}
|
|
196
195
|
);
|
|
197
196
|
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) => {
|
|
198
|
-
const { runWorkSwitch } = await import("./work-
|
|
197
|
+
const { runWorkSwitch } = await import("./work-KEPTGZ6H.js");
|
|
199
198
|
await runWorkSwitch(id);
|
|
200
199
|
});
|
|
201
200
|
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) => {
|
|
202
|
-
const { runWorkAbandon } = await import("./work-
|
|
201
|
+
const { runWorkAbandon } = await import("./work-KEPTGZ6H.js");
|
|
203
202
|
runWorkAbandon(id);
|
|
204
203
|
});
|
|
205
204
|
work.command("done <id>").description(
|
|
206
205
|
"\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)"
|
|
207
206
|
).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) => {
|
|
208
|
-
const { runWorkDone } = await import("./work-
|
|
207
|
+
const { runWorkDone } = await import("./work-KEPTGZ6H.js");
|
|
209
208
|
await runWorkDone(id, { force: opts.force === true });
|
|
210
209
|
});
|
|
211
210
|
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)");
|
|
212
211
|
lane.option("--json", "\uAE30\uACC4\uAC00 \uC77D\uC744 \uC218 \uC788\uB294 JSON\uC73C\uB85C \uCD9C\uB825\uD569\uB2C8\uB2E4").action(async (opts) => {
|
|
213
|
-
const { runLaneList } = await import("./lane-
|
|
212
|
+
const { runLaneList } = await import("./lane-DAZISODH.js");
|
|
214
213
|
await runLaneList({ json: opts.json === true });
|
|
215
214
|
});
|
|
216
215
|
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) => {
|
|
217
|
-
const { runLaneNew } = await import("./lane-
|
|
216
|
+
const { runLaneNew } = await import("./lane-DAZISODH.js");
|
|
218
217
|
await runLaneNew(name, description);
|
|
219
218
|
});
|
|
220
219
|
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) => {
|
|
221
|
-
const { runLaneList } = await import("./lane-
|
|
220
|
+
const { runLaneList } = await import("./lane-DAZISODH.js");
|
|
222
221
|
await runLaneList({ json: opts.json === true });
|
|
223
222
|
});
|
|
224
223
|
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) => {
|
|
225
|
-
const { runLaneRemove } = await import("./lane-
|
|
224
|
+
const { runLaneRemove } = await import("./lane-DAZISODH.js");
|
|
226
225
|
await runLaneRemove(name, { force: opts.force === true });
|
|
227
226
|
});
|
|
228
227
|
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) => {
|
|
@@ -231,16 +230,16 @@ function buildProgram() {
|
|
|
231
230
|
});
|
|
232
231
|
const rules = program.command("rules").description("\uC774 \uD504\uB85C\uC81D\uD2B8\uC5D0 \uC801\uC6A9\uB418\uB294 \uADDC\uCE59\uC744 \uBD05\uB2C8\uB2E4").enablePositionalOptions();
|
|
233
232
|
rules.option("--scope <scope>", "\uBC94\uC704\uB85C \uAC70\uB985\uB2C8\uB2E4 (implement \uB4F1)").option("--json", "\uAE30\uACC4\uAC00 \uC77D\uC744 \uC218 \uC788\uB294 JSON\uC73C\uB85C \uCD9C\uB825\uD569\uB2C8\uB2E4").action(async (opts) => {
|
|
234
|
-
const { runRules } = await import("./rules-
|
|
233
|
+
const { runRules } = await import("./rules-R2UZPIVW.js");
|
|
235
234
|
runRules({ scope: opts.scope, json: opts.json === true });
|
|
236
235
|
});
|
|
237
236
|
rules.command("edit").description("$EDITOR \uB85C \uADDC\uCE59 \uD30C\uC77C\uC744 \uC5FD\uB2C8\uB2E4").action(async () => {
|
|
238
|
-
const { runRules } = await import("./rules-
|
|
237
|
+
const { runRules } = await import("./rules-R2UZPIVW.js");
|
|
239
238
|
runRules({ edit: true });
|
|
240
239
|
});
|
|
241
240
|
rules.command("promote <gotchaId>").description("\uAD50\uD6C8\uC744 \uADDC\uCE59\uC73C\uB85C \uC2B9\uACA9\uD569\uB2C8\uB2E4 (applies/counter \uD544\uC218, \uC0AC\uB78C\uC774 \uC2E4\uD589)").option("--applies <cond>", "\uC801\uC6A9 \uC870\uAC74 (\uD544\uC218)").option("--counter <cond>", "\uBC18\uC99D \uC870\uAC74 (\uD544\uC218)").option("--rule-scope <scope>", "\uB85C\uB4DC \uB2E8\uACC4 (audit/criteria/implement/commit/review)").action(
|
|
242
241
|
async (gotchaId, opts) => {
|
|
243
|
-
const { runRulesPromote } = await import("./rules-
|
|
242
|
+
const { runRulesPromote } = await import("./rules-R2UZPIVW.js");
|
|
244
243
|
runRulesPromote(gotchaId, {
|
|
245
244
|
applies: opts.applies,
|
|
246
245
|
counter: opts.counter,
|
|
@@ -249,7 +248,7 @@ function buildProgram() {
|
|
|
249
248
|
}
|
|
250
249
|
);
|
|
251
250
|
program.command("gotchas").description("\uC544\uC9C1 \uADDC\uCE59\uC774 \uB418\uC9C0 \uC54A\uC740 \uD568\uC815\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) => {
|
|
252
|
-
const { runGotchas } = await import("./gotchas-
|
|
251
|
+
const { runGotchas } = await import("./gotchas-MCA5Y76R.js");
|
|
253
252
|
runGotchas({ json: opts.json === true });
|
|
254
253
|
});
|
|
255
254
|
program.command("metrics").description("\uC6CC\uD06C\uC544\uC774\uD15C(\uC138\uB300)\uBCC4 \uD504\uB85D\uC2DC \uC9C0\uD45C \uCD94\uC138\uB97C \uBD05\uB2C8\uB2E4 (\uD1A0\uD070 \uC9C1\uC811 \uCE21\uC815 \uC544\uB2D8)").option("--json", "\uAE30\uACC4\uAC00 \uC77D\uC744 \uC218 \uC788\uB294 JSON\uC73C\uB85C \uCD9C\uB825\uD569\uB2C8\uB2E4").option("--compare", "\uC2E4\uD5D8 \uCF00\uC774\uC2A4(experiment model/mode/taskType)\uBCC4\uB85C \uC9C0\uD45C\uB97C \uBE44\uAD50\uD569\uB2C8\uB2E4").action(async (opts) => {
|
|
@@ -292,7 +291,7 @@ function buildProgram() {
|
|
|
292
291
|
}
|
|
293
292
|
);
|
|
294
293
|
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) => {
|
|
295
|
-
const { runReview } = await import("./review-
|
|
294
|
+
const { runReview } = await import("./review-ZTHDJ47V.js");
|
|
296
295
|
await runReview(range, { json: opts.json === true, base: opts.base });
|
|
297
296
|
});
|
|
298
297
|
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(
|
|
@@ -311,7 +310,7 @@ function buildProgram() {
|
|
|
311
310
|
"\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)"
|
|
312
311
|
).action(
|
|
313
312
|
async (opts) => {
|
|
314
|
-
const { runVerify } = await import("./verify-
|
|
313
|
+
const { runVerify } = await import("./verify-L7ARTK42.js");
|
|
315
314
|
await runVerify({
|
|
316
315
|
json: opts.json === true,
|
|
317
316
|
bail: opts.bail === true,
|
|
@@ -322,7 +321,7 @@ function buildProgram() {
|
|
|
322
321
|
}
|
|
323
322
|
);
|
|
324
323
|
program.command("hold-recheck", { hidden: true }).description(".tasks/plan \uC758 \uC758\uC874\uD615 hold \uB97C \uC7AC\uC810\uAC80\uD574 \uCC29\uC9C0+\uD569\uACA9\uD55C \uC758\uC874\uC774\uBA74 \uC790\uB3D9 un-hold \uD569\uB2C8\uB2E4").option("--json", "\uAE30\uACC4\uAC00 \uC77D\uC744 \uC218 \uC788\uB294 JSON\uC73C\uB85C \uCD9C\uB825\uD569\uB2C8\uB2E4").action(async (opts) => {
|
|
325
|
-
const { runHoldRecheck } = await import("./hold-recheck-
|
|
324
|
+
const { runHoldRecheck } = await import("./hold-recheck-WN5EG7HD.js");
|
|
326
325
|
await runHoldRecheck({ json: opts.json === true });
|
|
327
326
|
});
|
|
328
327
|
const state = program.command("state", { hidden: true }).description("\uB8E8\uD504 \uC0C1\uD0DC\uB97C \uC77D\uACE0 \uC501\uB2C8\uB2E4");
|
|
@@ -343,7 +342,7 @@ function buildProgram() {
|
|
|
343
342
|
});
|
|
344
343
|
program.command("evolve", { hidden: true }).description("\uAE30\uB85D\uC744 \uBAA8\uC544 \uAD50\uD6C8\uC73C\uB85C, \uAD50\uD6C8\uC744 \uADDC\uCE59\uC73C\uB85C \uC787\uC2B5\uB2C8\uB2E4").option("--collect", "\uC774\uBC88 \uC6CC\uD06C\uC544\uC774\uD15C\uC758 \uAE30\uB85D\uC744 \uBAA8\uC544 JSON\uC73C\uB85C \uCD9C\uB825\uD569\uB2C8\uB2E4").option("--record", "\uAD50\uD6C8\uC744 gotchas \uC5D0 \uAE30\uB85D\uD569\uB2C8\uB2E4 (--json \uC73C\uB85C \uB370\uC774\uD130)").option("--json [data]", "collect: \uCD9C\uB825 \uD50C\uB798\uADF8 / record: \uAD50\uD6C8 \uB370\uC774\uD130(JSON \uBB38\uC790\uC5F4)").option("--workitem <wi>", "\uC6CC\uD06C\uC544\uC774\uD15C\uC73C\uB85C \uAC70\uB985\uB2C8\uB2E4 (--collect)").option("--from <YYYY-MM>", "\uAE30\uAC04 \uC2DC\uC791 \uC6D4\uB85C \uC77D\uAE30\uB97C \uC881\uD799\uB2C8\uB2E4 (--collect, \uC5C6\uC73C\uBA74 \uC804\uB7C9)").option("--to <YYYY-MM>", "\uAE30\uAC04 \uB05D \uC6D4 (--collect)").action(
|
|
345
344
|
async (opts) => {
|
|
346
|
-
const m = await import("./evolve-
|
|
345
|
+
const m = await import("./evolve-QPD7TWGO.js");
|
|
347
346
|
if (opts.collect && opts.record) {
|
|
348
347
|
process.stderr.write("\n --collect \uC640 --record \uB294 \uB3D9\uC2DC\uC5D0 \uC4F8 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.\n");
|
|
349
348
|
process.exit(1);
|
|
@@ -8,9 +8,9 @@ import {
|
|
|
8
8
|
gitHasCommits,
|
|
9
9
|
renderText,
|
|
10
10
|
runDoctor
|
|
11
|
-
} from "./chunk-
|
|
12
|
-
import "./chunk-
|
|
13
|
-
import "./chunk-
|
|
11
|
+
} from "./chunk-IXMAFR4Y.js";
|
|
12
|
+
import "./chunk-C7BR2DCS.js";
|
|
13
|
+
import "./chunk-YTAHVR4P.js";
|
|
14
14
|
import "./chunk-I77CXOEX.js";
|
|
15
15
|
import "./chunk-4OCSYHYB.js";
|
|
16
16
|
import "./chunk-UOPWVM2H.js";
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import {
|
|
2
2
|
pipelineLanes
|
|
3
|
-
} from "./chunk-
|
|
4
|
-
import "./chunk-
|
|
5
|
-
import "./chunk-
|
|
3
|
+
} from "./chunk-46HZN6UB.js";
|
|
4
|
+
import "./chunk-DP4O5ME2.js";
|
|
5
|
+
import "./chunk-ZE6HXOYG.js";
|
|
6
6
|
import "./chunk-D5OINC3G.js";
|
|
7
|
-
import "./chunk-
|
|
7
|
+
import "./chunk-QE2CLNBG.js";
|
|
8
8
|
import "./chunk-6E7XEQOH.js";
|
|
9
|
-
import "./chunk-
|
|
10
|
-
import "./chunk-
|
|
11
|
-
import "./chunk-
|
|
12
|
-
import "./chunk-
|
|
13
|
-
import "./chunk-
|
|
9
|
+
import "./chunk-IXMAFR4Y.js";
|
|
10
|
+
import "./chunk-C7BR2DCS.js";
|
|
11
|
+
import "./chunk-YTAHVR4P.js";
|
|
12
|
+
import "./chunk-IMB46O6S.js";
|
|
13
|
+
import "./chunk-G5LAJ5TV.js";
|
|
14
14
|
import "./chunk-F5LHXBH7.js";
|
|
15
15
|
import "./chunk-I77CXOEX.js";
|
|
16
16
|
import "./chunk-4OCSYHYB.js";
|
|
@@ -10,16 +10,16 @@ import {
|
|
|
10
10
|
runLaneRemove,
|
|
11
11
|
unmergedCommitCount,
|
|
12
12
|
worktreeUntracked
|
|
13
|
-
} from "./chunk-
|
|
14
|
-
import "./chunk-
|
|
13
|
+
} from "./chunk-DP4O5ME2.js";
|
|
14
|
+
import "./chunk-ZE6HXOYG.js";
|
|
15
15
|
import "./chunk-D5OINC3G.js";
|
|
16
|
-
import "./chunk-
|
|
16
|
+
import "./chunk-QE2CLNBG.js";
|
|
17
17
|
import "./chunk-6E7XEQOH.js";
|
|
18
|
-
import "./chunk-
|
|
19
|
-
import "./chunk-
|
|
20
|
-
import "./chunk-
|
|
21
|
-
import "./chunk-
|
|
22
|
-
import "./chunk-
|
|
18
|
+
import "./chunk-IXMAFR4Y.js";
|
|
19
|
+
import "./chunk-C7BR2DCS.js";
|
|
20
|
+
import "./chunk-YTAHVR4P.js";
|
|
21
|
+
import "./chunk-IMB46O6S.js";
|
|
22
|
+
import "./chunk-G5LAJ5TV.js";
|
|
23
23
|
import "./chunk-F5LHXBH7.js";
|
|
24
24
|
import "./chunk-I77CXOEX.js";
|
|
25
25
|
import "./chunk-4OCSYHYB.js";
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import {
|
|
2
2
|
runVerifyChecks
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-QE2CLNBG.js";
|
|
4
4
|
import "./chunk-6E7XEQOH.js";
|
|
5
|
-
import "./chunk-
|
|
6
|
-
import "./chunk-
|
|
7
|
-
import "./chunk-
|
|
5
|
+
import "./chunk-IXMAFR4Y.js";
|
|
6
|
+
import "./chunk-C7BR2DCS.js";
|
|
7
|
+
import "./chunk-YTAHVR4P.js";
|
|
8
8
|
import {
|
|
9
9
|
filterRules,
|
|
10
10
|
loadRules
|
|
11
|
-
} from "./chunk-
|
|
12
|
-
import "./chunk-
|
|
11
|
+
} from "./chunk-IMB46O6S.js";
|
|
12
|
+
import "./chunk-G5LAJ5TV.js";
|
|
13
13
|
import "./chunk-F5LHXBH7.js";
|
|
14
14
|
import "./chunk-I77CXOEX.js";
|
|
15
15
|
import {
|
|
@@ -10,8 +10,8 @@ import {
|
|
|
10
10
|
runRulesPromote,
|
|
11
11
|
suggestLinter,
|
|
12
12
|
validatePromoteOpts
|
|
13
|
-
} from "./chunk-
|
|
14
|
-
import "./chunk-
|
|
13
|
+
} from "./chunk-IMB46O6S.js";
|
|
14
|
+
import "./chunk-G5LAJ5TV.js";
|
|
15
15
|
import "./chunk-F5LHXBH7.js";
|
|
16
16
|
import "./chunk-I77CXOEX.js";
|
|
17
17
|
import "./chunk-4OCSYHYB.js";
|
|
@@ -9,17 +9,17 @@ import {
|
|
|
9
9
|
renderPipelineGroups,
|
|
10
10
|
renderStatus,
|
|
11
11
|
runStatus
|
|
12
|
-
} from "./chunk-
|
|
13
|
-
import "./chunk-
|
|
14
|
-
import "./chunk-
|
|
12
|
+
} from "./chunk-46HZN6UB.js";
|
|
13
|
+
import "./chunk-DP4O5ME2.js";
|
|
14
|
+
import "./chunk-ZE6HXOYG.js";
|
|
15
15
|
import "./chunk-D5OINC3G.js";
|
|
16
|
-
import "./chunk-
|
|
16
|
+
import "./chunk-QE2CLNBG.js";
|
|
17
17
|
import "./chunk-6E7XEQOH.js";
|
|
18
|
-
import "./chunk-
|
|
19
|
-
import "./chunk-
|
|
20
|
-
import "./chunk-
|
|
21
|
-
import "./chunk-
|
|
22
|
-
import "./chunk-
|
|
18
|
+
import "./chunk-IXMAFR4Y.js";
|
|
19
|
+
import "./chunk-C7BR2DCS.js";
|
|
20
|
+
import "./chunk-YTAHVR4P.js";
|
|
21
|
+
import "./chunk-IMB46O6S.js";
|
|
22
|
+
import "./chunk-G5LAJ5TV.js";
|
|
23
23
|
import "./chunk-F5LHXBH7.js";
|
|
24
24
|
import "./chunk-I77CXOEX.js";
|
|
25
25
|
import "./chunk-4OCSYHYB.js";
|
|
@@ -4,19 +4,19 @@ import {
|
|
|
4
4
|
laneBranchMap,
|
|
5
5
|
unmergedCommitCount,
|
|
6
6
|
worktreeUntracked
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-DP4O5ME2.js";
|
|
8
8
|
import {
|
|
9
9
|
removeGitWorktree,
|
|
10
10
|
worktreeDirtyTracked
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-ZE6HXOYG.js";
|
|
12
12
|
import "./chunk-D5OINC3G.js";
|
|
13
|
-
import "./chunk-
|
|
13
|
+
import "./chunk-QE2CLNBG.js";
|
|
14
14
|
import "./chunk-6E7XEQOH.js";
|
|
15
|
-
import "./chunk-
|
|
16
|
-
import "./chunk-
|
|
17
|
-
import "./chunk-
|
|
18
|
-
import "./chunk-
|
|
19
|
-
import "./chunk-
|
|
15
|
+
import "./chunk-IXMAFR4Y.js";
|
|
16
|
+
import "./chunk-C7BR2DCS.js";
|
|
17
|
+
import "./chunk-YTAHVR4P.js";
|
|
18
|
+
import "./chunk-IMB46O6S.js";
|
|
19
|
+
import "./chunk-G5LAJ5TV.js";
|
|
20
20
|
import "./chunk-F5LHXBH7.js";
|
|
21
21
|
import "./chunk-I77CXOEX.js";
|
|
22
22
|
import "./chunk-4OCSYHYB.js";
|
|
@@ -11,11 +11,11 @@ import {
|
|
|
11
11
|
substituteRelatedCmd,
|
|
12
12
|
verifyBaselinePath,
|
|
13
13
|
writeVerifyBaseline
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-QE2CLNBG.js";
|
|
15
15
|
import "./chunk-6E7XEQOH.js";
|
|
16
|
-
import "./chunk-
|
|
17
|
-
import "./chunk-
|
|
18
|
-
import "./chunk-
|
|
16
|
+
import "./chunk-IXMAFR4Y.js";
|
|
17
|
+
import "./chunk-C7BR2DCS.js";
|
|
18
|
+
import "./chunk-YTAHVR4P.js";
|
|
19
19
|
import "./chunk-I77CXOEX.js";
|
|
20
20
|
import "./chunk-4OCSYHYB.js";
|
|
21
21
|
import "./chunk-UOPWVM2H.js";
|
|
@@ -2,8 +2,8 @@ import {
|
|
|
2
2
|
gatherVersionInputs,
|
|
3
3
|
renderVersionCheck,
|
|
4
4
|
runVersionCheck
|
|
5
|
-
} from "./chunk-
|
|
6
|
-
import "./chunk-
|
|
5
|
+
} from "./chunk-C7BR2DCS.js";
|
|
6
|
+
import "./chunk-YTAHVR4P.js";
|
|
7
7
|
import "./chunk-UOPWVM2H.js";
|
|
8
8
|
import "./chunk-BUWGQVHT.js";
|
|
9
9
|
import "./chunk-7SYRDDTX.js";
|
|
@@ -15,15 +15,15 @@ import {
|
|
|
15
15
|
summarizeWorkitems,
|
|
16
16
|
withCostAtStart,
|
|
17
17
|
worktreeDirtyTracked
|
|
18
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-ZE6HXOYG.js";
|
|
19
19
|
import "./chunk-D5OINC3G.js";
|
|
20
|
-
import "./chunk-
|
|
20
|
+
import "./chunk-QE2CLNBG.js";
|
|
21
21
|
import "./chunk-6E7XEQOH.js";
|
|
22
|
-
import "./chunk-
|
|
23
|
-
import "./chunk-
|
|
24
|
-
import "./chunk-
|
|
25
|
-
import "./chunk-
|
|
26
|
-
import "./chunk-
|
|
22
|
+
import "./chunk-IXMAFR4Y.js";
|
|
23
|
+
import "./chunk-C7BR2DCS.js";
|
|
24
|
+
import "./chunk-YTAHVR4P.js";
|
|
25
|
+
import "./chunk-IMB46O6S.js";
|
|
26
|
+
import "./chunk-G5LAJ5TV.js";
|
|
27
27
|
import "./chunk-F5LHXBH7.js";
|
|
28
28
|
import "./chunk-I77CXOEX.js";
|
|
29
29
|
import "./chunk-4OCSYHYB.js";
|
|
@@ -79,5 +79,11 @@ awl은 스폰하지 않으므로(위 "awl은 스폰하지 않는다") 에이전
|
|
|
79
79
|
|
|
80
80
|
**wall-clock ≠개별 합/평균 — 섞지 않는다.** 레인이 여러 개면 병렬로 돌아 사이클 wall-clock이 workitem별 durationMs 합/평균보다 작을 수 있다(둘은 다른 걸 잰다). 헤드라인의 "총 소요시간"은 반드시 오케스트레이터가 실측한 wall-clock 값이고, 엔진 집계가 돌려주는 `efficiency.durationMs`(있는 값만 평균 — `awl loop-summary` AC-02 규약)는 참고용으로 별도 줄에 낸다. 두 수치를 하나로 합치거나 wall-clock 자리에 집계 평균을 대신 쓰지 않는다.
|
|
81
81
|
|
|
82
|
+
**반복 gotcha 승격 후보 안내.** `awl rules promote`는 사람이 명시적으로 실행해야 승격된다(자동 승격 없음 — `docs/presentation/storyline.md` 5절 "졸업 메커니즘" 원칙). 그 알림은 `awl evolve` 실행 시점에 콘솔 한 줄로만 뜨는데, exec/review가 서브에이전트로 도는 무인 사이클에서는 이 한 줄이 사람 눈에 안 닿는다 — `gate-low`/`gate-medium`처럼 게이트를 사람이 매번 안 보는 모드일수록 더 그렇다. 그래서 3단계 종료 보고에 매번 이 확인을 끼워 넣는다:
|
|
83
|
+
1. `awl gotchas --json`으로 전체 gotcha를 가져와 `count >= 2`인 항목을 추린다.
|
|
84
|
+
2. `~/.awl/rules/active/*.md` 각 파일의 frontmatter `source:` 값(`awl rules promote`가 새겨 넣는 원본 gotcha id — `runRulesPromote`/`buildRuleFile` 참고)을 모아, 이미 승격된 gotcha id 집합을 만든다. (`awl rules --json`은 이 필드를 안 돌려준다 — 파일을 직접 읽어야 한다.)
|
|
85
|
+
3. (1) - (2) = 아직 승격 안 된 반복 gotcha. 비어 있으면 아무 말도 안 한다(매 사이클 노이즈 방지).
|
|
86
|
+
4. 비어 있지 않으면 종료 보고 마지막에 표로 얹는다 — id·반복 횟수·교훈 요약. 그리고 한 줄: "이 함정들이 반복되고 있습니다. `awl rules promote <id> --applies "..." --counter "..."`로 규칙을 만들 수 있습니다 — 승격하면 다음부터는 검사기·리뷰 체크리스트가 놓치지 않고 잡아줍니다."
|
|
87
|
+
|
|
82
88
|
## 라이브 검증은 사람 몫 (경계)
|
|
83
89
|
이 스킬은 **스폰 계약·라우팅·mode·상태 규약을 인코딩**한다. 스폰이 실제로 한 사이클을 무인으로 도는지의 **라이브 수용은 사람 절차** `.tasks/pipeline-live-validation.md`(probe 레인에서 실제 케이스 완주 관측)로 분리한다. 스킬을 저작·정적 대조로 닫되, "스폰이 실증됐다"고 스스로 승인하지 않는다.
|
package/engine/version.json
CHANGED
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agent-work-loop",
|
|
3
|
-
"version": "0.6.
|
|
4
|
-
"description": "같은 실패를 두 번 하지
|
|
3
|
+
"version": "0.6.23",
|
|
4
|
+
"description": "같은 실패를 두 번 하지 않는 도구. AI 에이전트가 한 일과 확인한 내용을 파일로 남깁니다.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
7
|
"awl": "dist/cli.js"
|