agent-work-loop 0.6.27 → 0.6.31
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 +19 -8
- package/dist/{brief-TQND6XIK.js → brief-ZZSQ6RQS.js} +5 -5
- package/dist/{changelog-J4LP6ZJI.js → changelog-JWLVVHZL.js} +5 -5
- package/dist/{chunk-J7EKKHVW.js → chunk-22SUY5RE.js} +6 -6
- package/dist/{chunk-PIOV3MQT.js → chunk-2DAP3QBU.js} +70 -31
- package/dist/{chunk-H4EMS47F.js → chunk-3UPF7LZT.js} +15 -5
- package/dist/{chunk-M4H4VNN6.js → chunk-45X7T64Y.js} +12 -11
- package/dist/{chunk-OSKS2YRU.js → chunk-5APWNDRG.js} +2 -2
- package/dist/{chunk-UB4RLTLJ.js → chunk-77EZYCLF.js} +2 -2
- package/dist/{chunk-PFXDX4JF.js → chunk-7NOHUUXV.js} +108 -11
- package/dist/{chunk-DR7OZZ4N.js → chunk-DIRYW77S.js} +5 -5
- package/dist/{chunk-CLWQEWEG.js → chunk-JPFGMDQ4.js} +38 -21
- package/dist/{chunk-DGPZEEFJ.js → chunk-Q7V3WVKT.js} +4 -4
- package/dist/{chunk-GKKWXRQA.js → chunk-RNZCRXE3.js} +5 -5
- package/dist/{chunk-MLD2GOVM.js → chunk-RRQYSRRT.js} +5 -5
- package/dist/{chunk-MCNUMMKK.js → chunk-SV4D72NX.js} +3 -3
- package/dist/{chunk-KJG2ULS4.js → chunk-TTZY2GLK.js} +1 -1
- package/dist/{chunk-JXFQHNHV.js → chunk-YP4VCWPV.js} +3 -3
- package/dist/{chunk-KNBSZQGN.js → chunk-Z3QCPOOA.js} +2 -2
- package/dist/cli.js +60 -52
- package/dist/{commit-2WWILQRB.js → commit-3UZE7XJM.js} +6 -6
- package/dist/{config-XMM3V7MT.js → config-DAD4LIWR.js} +3 -3
- package/dist/{doctor-HZEAQNY7.js → doctor-AW65MZKN.js} +8 -8
- package/dist/{evolve-EQ3N6F6M.js → evolve-K4WKRA6U.js} +7 -7
- package/dist/{feedback-4FT67LSI.js → feedback-3C33YHKF.js} +5 -5
- package/dist/{gotchas-QJBUVYJV.js → gotchas-IGEQILOO.js} +7 -7
- package/dist/{hold-recheck-L3DAS3MV.js → hold-recheck-THSJKF5G.js} +16 -16
- package/dist/{init-PTTYGP2D.js → init-MRJEU7IR.js} +6 -2
- package/dist/lane-ZQVD7EDE.js +41 -0
- package/dist/{loop-summary-OSYJB57M.js → loop-summary-MPEKQ2EC.js} +6 -6
- package/dist/{metrics-BC7ZUCGU.js → metrics-64WBBQQX.js} +4 -4
- package/dist/{record-CKR6G6UZ.js → record-GAWMF7KL.js} +5 -5
- package/dist/{uninstall-JECZJNRJ.js → remove-ELP4MFVE.js} +19 -19
- package/dist/{review-UJH6C7F4.js → review-A5Q7NSOD.js} +13 -13
- package/dist/{rules-E52GU3GA.js → rules-BEQT7YVN.js} +8 -8
- package/dist/{state-X7DLLBOD.js → state-RDKIOU25.js} +4 -4
- package/dist/status-FP73XOZS.js +40 -0
- package/dist/update-7RQQJ2TH.js +135 -0
- package/dist/{verify-KKQ2OQMO.js → verify-UUJ6KD37.js} +10 -10
- package/dist/version-check-H2T3WW3I.js +14 -0
- package/dist/{work-3SONYYYB.js → work-HWJSUWBR.js} +14 -14
- package/engine/version.json +1 -1
- package/package.json +1 -1
- package/dist/lane-WINQEOEW.js +0 -41
- package/dist/status-NGSQ4XK3.js +0 -40
- package/dist/update-GA6I4AMF.js +0 -61
- package/dist/version-check-7XE232L3.js +0 -14
package/README.md
CHANGED
|
@@ -43,22 +43,33 @@ yarn global add agent-work-loop
|
|
|
43
43
|
> ```
|
|
44
44
|
> `dist/cli.js`가 `awl` bin으로 등록됩니다. 정식 npm 배포가 되면 이 문단은 지웁니다.
|
|
45
45
|
|
|
46
|
-
###
|
|
46
|
+
### 업데이트 하기
|
|
47
47
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
48
|
+
```
|
|
49
|
+
업데이트 하기:
|
|
50
|
+
1. npm i -g agent-work-loop@latest npm에 배포된 최신 버전을 받습니다
|
|
51
|
+
2. awl update 설치된 패키지로 전역 엔진(~/.awl/engine)을 갱신합니다
|
|
52
52
|
```
|
|
53
53
|
|
|
54
|
-
pnpm이나 yarn을
|
|
54
|
+
pnpm이나 yarn을 쓴다면 1번만 그 도구로 바꿉니다:
|
|
55
55
|
|
|
56
56
|
```bash
|
|
57
57
|
pnpm add -g agent-work-loop@latest
|
|
58
58
|
yarn global add agent-work-loop@latest
|
|
59
59
|
```
|
|
60
60
|
|
|
61
|
-
|
|
61
|
+
`awl update`(옵션 없음)는 `awl update --global`과 같습니다. 전역 엔진만 갱신하고 어떤 프로젝트도 건드리지 않습니다. 대부분은 이 두 줄이면 끝입니다.
|
|
62
|
+
|
|
63
|
+
**여러 프로젝트를 관리하는 입장이라면** 등록된 프로젝트들의 로컬 스킬(`.claude/skills`, `AGENTS.md`, `.awl/config.json`)까지 한 번에 맞추고 싶을 수 있습니다:
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
npm i -g agent-work-loop@latest
|
|
67
|
+
awl update --all
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
`--all`은 전역 엔진과 `~/.awl/projects.json`에 등록된 프로젝트 전부의 로컬 스킬을 갱신하고, 끝에 바뀐 프로젝트 목록과 "커밋하세요" 안내를 보여줍니다. 등록된 프로젝트만 로컬을 건드리고 싶으면 `--local`만 씁니다.
|
|
71
|
+
|
|
72
|
+
이렇게 갱신한 프로젝트를 커밋해서 push하면, 그 저장소를 쓰는 다른 사람들은 다음에 pull할 때 최신 스킬을 받습니다. **다만 자동으로 알림이 가는 구조는 아닙니다.** 각자 컴퓨터의 `~/.awl/engine`이 낡았는지는 그 사람이 `awl doctor`/`awl version-check`를 실행하거나 `/awl-loop`·`/awl-pipeline`을 실행할 때(버전 확인이 맨 처음 단계로 들어있습니다) 노란 경고로 보게 됩니다.
|
|
62
73
|
|
|
63
74
|
설치가 됐는지 확인합니다:
|
|
64
75
|
|
|
@@ -349,7 +360,7 @@ awl work switch <ID> # 보관된 워크아이템으로 전환
|
|
|
349
360
|
스킬 문서가 게이트에서 반드시 도구를 호출하도록 지시돼 있습니다. 계속 안 멈추면 스킬이 최신인지 확인하세요. `awl doctor`가 `claude-skill-vs-engine` 불일치를 경고하면 `awl init --yes`로 재설치합니다.
|
|
350
361
|
|
|
351
362
|
**awl을 완전히 제거하려면**
|
|
352
|
-
`awl
|
|
363
|
+
`awl remove`를 실행합니다. 기본은 드라이런이라 먼저 무엇이 지워질지 보여주고, 실제로 지우려면 `--yes`를 붙입니다. 기본은 이 프로젝트만 지우고, `~/.awl`까지 지우려면 `--global`을 명시해야 합니다. 자세한 플래그와 실제 출력은 [`commands.md`의 `awl remove`](docs/presentation/commands.md#awl-remove)를 참고하세요.
|
|
353
364
|
|
|
354
365
|
---
|
|
355
366
|
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import {
|
|
2
2
|
loadProjectName,
|
|
3
3
|
readRecords
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-YP4VCWPV.js";
|
|
5
5
|
import {
|
|
6
6
|
loadState
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-77EZYCLF.js";
|
|
8
8
|
import {
|
|
9
9
|
resolveProjectRoot,
|
|
10
10
|
run
|
|
11
|
-
} from "./chunk-
|
|
12
|
-
import "./chunk-
|
|
13
|
-
import "./chunk-
|
|
11
|
+
} from "./chunk-JPFGMDQ4.js";
|
|
12
|
+
import "./chunk-2DAP3QBU.js";
|
|
13
|
+
import "./chunk-45X7T64Y.js";
|
|
14
14
|
|
|
15
15
|
// src/commands/brief.ts
|
|
16
16
|
var KST_OFFSET_MS = 9 * 60 * 60 * 1e3;
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import {
|
|
2
2
|
readRecords
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-YP4VCWPV.js";
|
|
4
4
|
import {
|
|
5
5
|
loadState
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-77EZYCLF.js";
|
|
7
7
|
import {
|
|
8
8
|
resolveProjectRoot
|
|
9
|
-
} from "./chunk-
|
|
10
|
-
import "./chunk-
|
|
9
|
+
} from "./chunk-JPFGMDQ4.js";
|
|
10
|
+
import "./chunk-2DAP3QBU.js";
|
|
11
11
|
import {
|
|
12
12
|
caps,
|
|
13
13
|
signal
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-45X7T64Y.js";
|
|
15
15
|
|
|
16
16
|
// src/commands/changelog.ts
|
|
17
17
|
function runChangelogDraft(opts) {
|
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
import {
|
|
2
2
|
gatherVersionInputs
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-Q7V3WVKT.js";
|
|
4
4
|
import {
|
|
5
5
|
checkVersions
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-SV4D72NX.js";
|
|
7
7
|
import {
|
|
8
8
|
loadProjectName,
|
|
9
9
|
readRecords
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-YP4VCWPV.js";
|
|
11
11
|
import {
|
|
12
12
|
loadState,
|
|
13
13
|
readStateLock
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-77EZYCLF.js";
|
|
15
15
|
import {
|
|
16
16
|
CommandNotFoundError,
|
|
17
17
|
run,
|
|
18
18
|
tokenize
|
|
19
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-JPFGMDQ4.js";
|
|
20
20
|
import {
|
|
21
21
|
caps,
|
|
22
22
|
clipToWidth,
|
|
@@ -32,7 +32,7 @@ import {
|
|
|
32
32
|
sectionBox,
|
|
33
33
|
signal,
|
|
34
34
|
visibleWidth
|
|
35
|
-
} from "./chunk-
|
|
35
|
+
} from "./chunk-45X7T64Y.js";
|
|
36
36
|
|
|
37
37
|
// src/commands/doctor.ts
|
|
38
38
|
import fs from "fs";
|
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
sectionBox,
|
|
13
13
|
signal,
|
|
14
14
|
stringWidth
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-45X7T64Y.js";
|
|
16
16
|
|
|
17
17
|
// src/commands/init.ts
|
|
18
18
|
import fs from "fs";
|
|
@@ -311,7 +311,7 @@ function anyWorkspaceMemberHasTsconfig(cwd, pkg) {
|
|
|
311
311
|
}
|
|
312
312
|
return false;
|
|
313
313
|
}
|
|
314
|
-
function
|
|
314
|
+
function detectJsLanguage(cwd) {
|
|
315
315
|
if (exists(path.join(cwd, "tsconfig.json"))) {
|
|
316
316
|
return "typescript";
|
|
317
317
|
}
|
|
@@ -323,11 +323,25 @@ function detectLanguage(cwd) {
|
|
|
323
323
|
}
|
|
324
324
|
return "javascript";
|
|
325
325
|
}
|
|
326
|
-
if (exists(path.join(cwd, "pyproject.toml")) || exists(path.join(cwd, "setup.py")) || exists(path.join(cwd, "requirements.txt"))) {
|
|
327
|
-
return "python";
|
|
328
|
-
}
|
|
329
326
|
return null;
|
|
330
327
|
}
|
|
328
|
+
function hasPythonMarkers(cwd) {
|
|
329
|
+
return exists(path.join(cwd, "pyproject.toml")) || exists(path.join(cwd, "setup.py")) || exists(path.join(cwd, "requirements.txt"));
|
|
330
|
+
}
|
|
331
|
+
function detectLanguage(cwd) {
|
|
332
|
+
return detectJsLanguage(cwd) ?? (hasPythonMarkers(cwd) ? "python" : null);
|
|
333
|
+
}
|
|
334
|
+
function detectLanguages(cwd) {
|
|
335
|
+
const out = [];
|
|
336
|
+
const js = detectJsLanguage(cwd);
|
|
337
|
+
if (js) {
|
|
338
|
+
out.push(js);
|
|
339
|
+
}
|
|
340
|
+
if (hasPythonMarkers(cwd)) {
|
|
341
|
+
out.push("python");
|
|
342
|
+
}
|
|
343
|
+
return out;
|
|
344
|
+
}
|
|
331
345
|
function splitEnv(script) {
|
|
332
346
|
const env = {};
|
|
333
347
|
let rest = script.trim();
|
|
@@ -608,7 +622,7 @@ function nonInteractiveInputs(projectRoot) {
|
|
|
608
622
|
const skills = detected.claude || detected.codex ? detected : { claude: true, codex: false };
|
|
609
623
|
return {
|
|
610
624
|
project: path.basename(projectRoot),
|
|
611
|
-
mainLanguage:
|
|
625
|
+
mainLanguage: detectLanguages(projectRoot),
|
|
612
626
|
character: "",
|
|
613
627
|
verify: detectVerify(projectRoot),
|
|
614
628
|
skills
|
|
@@ -736,14 +750,17 @@ function renderResult(result, inputs, c) {
|
|
|
736
750
|
}
|
|
737
751
|
var LANG_OPTIONS = ["TypeScript", "JavaScript", "Python", "\uC9C1\uC811 \uC785\uB825"];
|
|
738
752
|
var LANG_VALUES = ["typescript", "javascript", "python", ""];
|
|
739
|
-
function
|
|
740
|
-
const detected =
|
|
741
|
-
|
|
742
|
-
|
|
753
|
+
function langDefaultIndices(projectRoot) {
|
|
754
|
+
const detected = detectLanguages(projectRoot);
|
|
755
|
+
if (detected.length === 0) {
|
|
756
|
+
return [0];
|
|
757
|
+
}
|
|
758
|
+
const indices = detected.map((lang) => LANG_VALUES.indexOf(lang)).filter((i) => i >= 0);
|
|
759
|
+
return indices.length > 0 ? indices : [0];
|
|
743
760
|
}
|
|
744
761
|
function buildScreens(projectRoot, hasGlobal, c) {
|
|
745
762
|
const project = path.basename(projectRoot);
|
|
746
|
-
const
|
|
763
|
+
const defLangIndices = langDefaultIndices(projectRoot);
|
|
747
764
|
const verify = detectVerify(projectRoot);
|
|
748
765
|
const agents = detectAgents(projectRoot);
|
|
749
766
|
const welcome = hasGlobal ? null : [
|
|
@@ -760,12 +777,13 @@ function buildScreens(projectRoot, hasGlobal, c) {
|
|
|
760
777
|
" \uADDC\uCE59\uACFC \uAD50\uD6C8\uC740 \uD504\uB85C\uC81D\uD2B8\uAC00 \uC544\uB2C8\uB77C \uB2F9\uC2E0\uC5D0\uAC8C \uC313\uC774\uACE0,",
|
|
761
778
|
" \uB4F1\uB85D\uB41C \uBAA8\uB4E0 \uD504\uB85C\uC81D\uD2B8\uC5D0\uC11C \uD568\uAED8 \uC4F0\uC785\uB2C8\uB2E4."
|
|
762
779
|
].join("\n");
|
|
780
|
+
const detectedLangLabels = defLangIndices.map((i) => LANG_OPTIONS[i] ?? "TypeScript").join(", ");
|
|
763
781
|
const langLines = [
|
|
764
|
-
`\uC790\uB3D9 \uAC10\uC9C0: ${
|
|
782
|
+
`\uC790\uB3D9 \uAC10\uC9C0: ${detectedLangLabels || "TypeScript"}`,
|
|
765
783
|
"",
|
|
766
|
-
"\
|
|
767
|
-
"\
|
|
768
|
-
"\uD0A4 \uC785\uB825\uC744 \uC9C0\uC6D0\uD558\uC9C0 \uC54A\uB294 \uD130\uBBF8\uB110\uC5D0\uC11C\uB294 \uBC88\uD638\uB97C \uC785\uB825\uD560 \uC218 \uC788\uC2B5\uB2C8\uB2E4."
|
|
784
|
+
"\uC5EC\uB7EC \uAC1C\uB97C \uC4F0\uB294 \uD504\uB85C\uC81D\uD2B8\uBA74(\uC608: TypeScript \uD504\uB860\uD2B8 + Python \uBC31\uC5D4\uB4DC) \uC804\uBD80 \uACE0\uB974\uC138\uC694.",
|
|
785
|
+
"\u2191\u2193 \uB610\uB294 j/k \uB85C \uC774\uB3D9, Space \uB85C \uC120\uD0DD, Enter \uB85C \uD655\uC815\uD558\uC138\uC694.",
|
|
786
|
+
"\uD0A4 \uC785\uB825\uC744 \uC9C0\uC6D0\uD558\uC9C0 \uC54A\uB294 \uD130\uBBF8\uB110\uC5D0\uC11C\uB294 \uBC88\uD638\uB97C \uC27C\uD45C\uB85C \uC785\uB825\uD560 \uC218 \uC788\uC2B5\uB2C8\uB2E4."
|
|
769
787
|
];
|
|
770
788
|
return {
|
|
771
789
|
welcome,
|
|
@@ -904,21 +922,19 @@ async function interactiveInputs(projectRoot, hasGlobal, c) {
|
|
|
904
922
|
${screens.lang}
|
|
905
923
|
|
|
906
924
|
`);
|
|
907
|
-
const
|
|
925
|
+
const defaultLangChecked = langDefaultIndices(projectRoot);
|
|
926
|
+
const rawLanguage = useRawMode ? await runInteractiveSelect(LANG_OPTIONS, 0, true, c, defaultLangChecked, {
|
|
908
927
|
title: "\uC8FC \uC5B8\uC5B4",
|
|
909
|
-
hint: "\u2191\u2193 \uB610\uB294 j/k \uC774\uB3D9 \xB7
|
|
928
|
+
hint: "\u2191\u2193 \uB610\uB294 j/k \uC774\uB3D9 \xB7 Space \uC120\uD0DD \xB7 Enter \uD655\uC815 \xB7 Esc \uAE30\uBCF8\uAC12 \uC720\uC9C0"
|
|
910
929
|
}) : null;
|
|
911
|
-
const
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
let mainLanguage = LANG_VALUES[langIdx] ?? "";
|
|
920
|
-
if (langIdx === LANG_OPTIONS.length - 1) {
|
|
921
|
-
mainLanguage = (await ask(prompt(), " \uC8FC \uC5B8\uC5B4\uB97C \uC785\uB825\uD558\uC138\uC694: ")).trim();
|
|
930
|
+
const langChecked = rawLanguage?.checked ?? (useRawMode ? defaultLangChecked : await selectMulti(prompt(), LANG_OPTIONS, defaultLangChecked, c, false, "\uC8FC \uC5B8\uC5B4"));
|
|
931
|
+
const manualLangIdx = LANG_OPTIONS.length - 1;
|
|
932
|
+
const mainLanguage = langChecked.filter((i) => i !== manualLangIdx).map((i) => LANG_VALUES[i]).filter((v) => typeof v === "string" && v !== "");
|
|
933
|
+
if (langChecked.includes(manualLangIdx)) {
|
|
934
|
+
const typed = (await ask(prompt(), " \uC8FC \uC5B8\uC5B4\uB97C \uC785\uB825\uD558\uC138\uC694: ")).trim();
|
|
935
|
+
if (typed) {
|
|
936
|
+
mainLanguage.push(typed);
|
|
937
|
+
}
|
|
922
938
|
}
|
|
923
939
|
const rootVerify = detectVerify(projectRoot);
|
|
924
940
|
const located = await promptVerifyLocation(
|
|
@@ -1000,7 +1016,7 @@ async function handleExistingConfig(rl, projectRoot, c, now) {
|
|
|
1000
1016
|
process.stdout.write("\n .awl/config.json \uC774 \uC774\uBBF8 \uC788\uC2B5\uB2C8\uB2E4. \uD300\uC6D0\uC774 \uC124\uC815\uD574\uB450\uC5C8\uAD70\uC694.\n\n");
|
|
1001
1017
|
process.stdout.write(` \uD504\uB85C\uC81D\uD2B8 ${config?.project ?? "(\uC5C6\uC74C)"}
|
|
1002
1018
|
`);
|
|
1003
|
-
process.stdout.write(` \uC8FC \uC5B8\uC5B4 ${config?.mainLanguage
|
|
1019
|
+
process.stdout.write(` \uC8FC \uC5B8\uC5B4 ${config?.mainLanguage?.join(", ") || "(\uC5C6\uC74C)"}
|
|
1004
1020
|
`);
|
|
1005
1021
|
process.stdout.write(` \uC131\uACA9 ${config?.character || "(\uC5C6\uC74C)"}
|
|
1006
1022
|
`);
|
|
@@ -1056,7 +1072,7 @@ async function handleExistingConfig(rl, projectRoot, c, now) {
|
|
|
1056
1072
|
}
|
|
1057
1073
|
const merged = {
|
|
1058
1074
|
project: config?.project ?? path.basename(projectRoot),
|
|
1059
|
-
mainLanguage: config?.mainLanguage ??
|
|
1075
|
+
mainLanguage: config?.mainLanguage ?? [],
|
|
1060
1076
|
character: config?.character ?? "",
|
|
1061
1077
|
verify,
|
|
1062
1078
|
skills: { claude: false, codex: false }
|
|
@@ -1105,6 +1121,27 @@ function registeredProjectPaths() {
|
|
|
1105
1121
|
return /* @__PURE__ */ new Set();
|
|
1106
1122
|
}
|
|
1107
1123
|
}
|
|
1124
|
+
function listRegisteredProjects() {
|
|
1125
|
+
try {
|
|
1126
|
+
const raw = JSON.parse(fs.readFileSync(projectsFile(), "utf8"));
|
|
1127
|
+
if (!Array.isArray(raw)) {
|
|
1128
|
+
return [];
|
|
1129
|
+
}
|
|
1130
|
+
const out = [];
|
|
1131
|
+
for (const entry of raw) {
|
|
1132
|
+
if (entry && typeof entry === "object" && typeof entry.path === "string") {
|
|
1133
|
+
const e = entry;
|
|
1134
|
+
out.push({
|
|
1135
|
+
name: typeof e.name === "string" ? e.name : path.basename(e.path),
|
|
1136
|
+
path: e.path
|
|
1137
|
+
});
|
|
1138
|
+
}
|
|
1139
|
+
}
|
|
1140
|
+
return out;
|
|
1141
|
+
} catch {
|
|
1142
|
+
return [];
|
|
1143
|
+
}
|
|
1144
|
+
}
|
|
1108
1145
|
function excludeRegisteredProjects(candidates, registered) {
|
|
1109
1146
|
if (registered.size === 0) {
|
|
1110
1147
|
return candidates;
|
|
@@ -1149,7 +1186,7 @@ async function pickProjectRoot(cwd, c) {
|
|
|
1149
1186
|
}
|
|
1150
1187
|
const candidates = excludeRegisteredProjects(scanGitProjects(cwd), registeredProjectPaths());
|
|
1151
1188
|
const labels = [...candidates.map((p) => `${p.name} (${p.path})`), "\uC9C1\uC811 \uACBD\uB85C \uC785\uB825", "\uCDE8\uC18C"];
|
|
1152
|
-
const title = candidates.length > 0 ? "\uD504\uB85C\uC81D\uD2B8\uB97C \uACE0\uB974\uC138\uC694 (\uCD5C\uADFC \uC218\uC815\uC21C, \uCD5C\uB300 20)" : "\uD558\uC704\uC5D0 git \uD504\uB85C\uC81D\uD2B8\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4 \u2014 \uC9C1\uC811 \uC785\uB825\uD558\uAC70\uB098 \uCDE8\uC18C";
|
|
1189
|
+
const title = candidates.length > 0 ? "\uD504\uB85C\uC81D\uD2B8\uB97C \uACE0\uB974\uC138\uC694 (\uCD5C\uADFC \uC218\uC815\uC21C, \uCD5C\uB300 20)\n" : "\uD558\uC704\uC5D0 git \uD504\uB85C\uC81D\uD2B8\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4 \u2014 \uC9C1\uC811 \uC785\uB825\uD558\uAC70\uB098 \uCDE8\uC18C\n";
|
|
1153
1190
|
const choice = resolveProjectChoice(await select(labels, title), candidates);
|
|
1154
1191
|
if (choice.kind === "path") {
|
|
1155
1192
|
return choice.path;
|
|
@@ -1241,6 +1278,7 @@ ${renderResult(result, inputs, c)}
|
|
|
1241
1278
|
export {
|
|
1242
1279
|
scanGitProjects,
|
|
1243
1280
|
detectLanguage,
|
|
1281
|
+
detectLanguages,
|
|
1244
1282
|
splitEnv,
|
|
1245
1283
|
detectVerify,
|
|
1246
1284
|
detectWorkspacePackages,
|
|
@@ -1276,6 +1314,7 @@ export {
|
|
|
1276
1314
|
applyVerifyCwd,
|
|
1277
1315
|
resolveProjectChoice,
|
|
1278
1316
|
registeredProjectPaths,
|
|
1317
|
+
listRegisteredProjects,
|
|
1279
1318
|
excludeRegisteredProjects,
|
|
1280
1319
|
runInit
|
|
1281
1320
|
};
|
|
@@ -5,22 +5,25 @@ import {
|
|
|
5
5
|
runWorkNew,
|
|
6
6
|
sanitizeForGit,
|
|
7
7
|
worktreeDirtyTracked
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-7NOHUUXV.js";
|
|
9
|
+
import {
|
|
10
|
+
loadProjectName
|
|
11
|
+
} from "./chunk-YP4VCWPV.js";
|
|
9
12
|
import {
|
|
10
13
|
loadState,
|
|
11
14
|
writeState
|
|
12
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-77EZYCLF.js";
|
|
13
16
|
import {
|
|
14
17
|
resolveProjectRoot,
|
|
15
18
|
run
|
|
16
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-JPFGMDQ4.js";
|
|
17
20
|
import {
|
|
18
21
|
caps,
|
|
19
22
|
feedback,
|
|
20
23
|
makeColors,
|
|
21
24
|
sectionBox,
|
|
22
25
|
signal
|
|
23
|
-
} from "./chunk-
|
|
26
|
+
} from "./chunk-45X7T64Y.js";
|
|
24
27
|
|
|
25
28
|
// src/commands/lane.ts
|
|
26
29
|
import fs from "fs";
|
|
@@ -258,7 +261,8 @@ ${feedback(c, "error", `\uB808\uC778 \uBE0C\uB79C\uCE58 ${branch} \uC5D0 \uBCD1\
|
|
|
258
261
|
}
|
|
259
262
|
let merged = null;
|
|
260
263
|
try {
|
|
261
|
-
|
|
264
|
+
const project = loadProjectName(root) ?? path.basename(root);
|
|
265
|
+
merged = mergeIsolatedHome(path.join(lanePath, ".awl", "home"), { project, lane: laneName });
|
|
262
266
|
} catch (e) {
|
|
263
267
|
process.stderr.write(
|
|
264
268
|
`
|
|
@@ -287,6 +291,12 @@ ${feedback(c, "ok", `\uB808\uC778 \uC81C\uAC70 ${color.bold(laneName)}`, branch
|
|
|
287
291
|
if (merged && (merged.gotchasAdded > 0 || merged.rulesAdded > 0 || merged.generationsAdded > 0)) {
|
|
288
292
|
process.stdout.write(
|
|
289
293
|
` ${color.dim(`\uD559\uC2B5 \uC804\uC5ED \uBCD1\uD569 gotcha ${merged.gotchasAdded} \xB7 rule ${merged.rulesAdded} \xB7 generation ${merged.generationsAdded}`)}
|
|
294
|
+
`
|
|
295
|
+
);
|
|
296
|
+
}
|
|
297
|
+
if (merged && merged.recordsMerged > 0) {
|
|
298
|
+
process.stdout.write(
|
|
299
|
+
` ${color.dim(`records \uC804\uC5ED \uBCD1\uD569 ${merged.recordsMerged}\uAC74${merged.recordsArchivePath ? ` \xB7 \uC544\uCE74\uC774\uBE0C ${merged.recordsArchivePath}` : ""}`)}
|
|
290
300
|
`
|
|
291
301
|
);
|
|
292
302
|
}
|
|
@@ -399,17 +399,18 @@ function sectionBox(title, lines, c = caps(), minInnerWidth = 0) {
|
|
|
399
399
|
Math.min(HARD_MAX_WIDTH, viewportWidth() - (2 + pad * 2))
|
|
400
400
|
);
|
|
401
401
|
const wrapped = lines.flatMap((line) => wrapToWidth(line, maxInner, { hanging: true }));
|
|
402
|
-
const inner = Math.min(
|
|
403
|
-
maxInner,
|
|
404
|
-
Math.max(minInnerWidth, visibleWidth(title), ...wrapped.map(visibleWidth), 0)
|
|
405
|
-
);
|
|
406
402
|
const frame = (text) => t.frame(text);
|
|
407
|
-
const
|
|
408
|
-
const
|
|
409
|
-
const
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
403
|
+
const lastLogical = lines[lines.length - 1] ?? "";
|
|
404
|
+
const lastIsBranch = lastLogical.trimStart().startsWith(s.lastBranch);
|
|
405
|
+
const row = (text, isLast) => {
|
|
406
|
+
const closeThis = isLast && !lastIsBranch;
|
|
407
|
+
const left = closeThis ? `${s.boxBL}${s.boxH}` : s.boxV;
|
|
408
|
+
const gap = closeThis ? pad - 1 : pad;
|
|
409
|
+
return `${frame(left)}${" ".repeat(gap)}${text}`;
|
|
410
|
+
};
|
|
411
|
+
const safeTitle = truncateToWidth(title, maxInner);
|
|
412
|
+
const top = frame(`${s.boxTL}${s.boxH} `) + t.emphasis(t.accent(safeTitle));
|
|
413
|
+
return [top, ...wrapped.map((line, i) => row(line, i === wrapped.length - 1))].join("\n");
|
|
413
414
|
}
|
|
414
415
|
var RESET = "\x1B[0m";
|
|
415
416
|
function ansi(code, str, enabled) {
|
|
@@ -430,7 +431,7 @@ function makeTokens(c) {
|
|
|
430
431
|
}
|
|
431
432
|
function signal(c, kind) {
|
|
432
433
|
const color2 = makeColors(c.color);
|
|
433
|
-
const raw =
|
|
434
|
+
const raw = { ok: "[ok]", warn: "[!]", error: "[x]", info: "[i]" }[kind];
|
|
434
435
|
if (kind === "ok") {
|
|
435
436
|
return color2.green(raw);
|
|
436
437
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
requireConfig
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-JPFGMDQ4.js";
|
|
4
4
|
import {
|
|
5
5
|
caps,
|
|
6
6
|
generationsDir,
|
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
padEndDisplay,
|
|
9
9
|
sectionBox,
|
|
10
10
|
stringWidth
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-45X7T64Y.js";
|
|
12
12
|
|
|
13
13
|
// src/commands/metrics.ts
|
|
14
14
|
import fs from "fs";
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
2
|
resolveProjectRoot
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-JPFGMDQ4.js";
|
|
4
4
|
import {
|
|
5
5
|
caps,
|
|
6
6
|
makeColors,
|
|
7
7
|
sectionBox
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-45X7T64Y.js";
|
|
9
9
|
|
|
10
10
|
// src/commands/state.ts
|
|
11
11
|
import fs from "fs";
|
|
@@ -7,29 +7,32 @@ import {
|
|
|
7
7
|
isCheckPassed,
|
|
8
8
|
runVerifyChecks,
|
|
9
9
|
writeVerifyBaseline
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-RRQYSRRT.js";
|
|
11
11
|
import {
|
|
12
12
|
gitBranch
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-22SUY5RE.js";
|
|
14
14
|
import {
|
|
15
15
|
parseRuleFile
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-Z3QCPOOA.js";
|
|
17
17
|
import {
|
|
18
18
|
nextGotchaId
|
|
19
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-DIRYW77S.js";
|
|
20
|
+
import {
|
|
21
|
+
loadProjectName
|
|
22
|
+
} from "./chunk-YP4VCWPV.js";
|
|
20
23
|
import {
|
|
21
24
|
loadState,
|
|
22
25
|
migrateState,
|
|
23
26
|
writeState
|
|
24
|
-
} from "./chunk-
|
|
27
|
+
} from "./chunk-77EZYCLF.js";
|
|
25
28
|
import {
|
|
26
29
|
loadConfig,
|
|
27
30
|
resolveProjectRoot,
|
|
28
31
|
run
|
|
29
|
-
} from "./chunk-
|
|
32
|
+
} from "./chunk-JPFGMDQ4.js";
|
|
30
33
|
import {
|
|
31
34
|
installClaudeSkill
|
|
32
|
-
} from "./chunk-
|
|
35
|
+
} from "./chunk-2DAP3QBU.js";
|
|
33
36
|
import {
|
|
34
37
|
caps,
|
|
35
38
|
feedback,
|
|
@@ -39,7 +42,7 @@ import {
|
|
|
39
42
|
makeTokens,
|
|
40
43
|
sectionBox,
|
|
41
44
|
signal
|
|
42
|
-
} from "./chunk-
|
|
45
|
+
} from "./chunk-45X7T64Y.js";
|
|
43
46
|
|
|
44
47
|
// src/commands/work.ts
|
|
45
48
|
import fs2 from "fs";
|
|
@@ -213,6 +216,88 @@ function mergeIsolatedLearning(fromRoot, toRoot) {
|
|
|
213
216
|
const generationsAdded = copyGenerations(fromRoot, toRoot);
|
|
214
217
|
return { gotchasAdded: added.length, rulesAdded, generationsAdded };
|
|
215
218
|
}
|
|
219
|
+
function recordFiles(root) {
|
|
220
|
+
const dir = path.join(root, "records");
|
|
221
|
+
try {
|
|
222
|
+
return fs.readdirSync(dir).filter((f) => f.endsWith(".jsonl")).sort();
|
|
223
|
+
} catch {
|
|
224
|
+
return [];
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
function monthOf(at) {
|
|
228
|
+
return at.slice(0, 7);
|
|
229
|
+
}
|
|
230
|
+
function copyRecordDiffs(fromRoot, toRoot) {
|
|
231
|
+
const fromDir = path.join(fromRoot, "records", "diffs");
|
|
232
|
+
if (!fs.existsSync(fromDir)) {
|
|
233
|
+
return;
|
|
234
|
+
}
|
|
235
|
+
const toDir = path.join(toRoot, "records", "diffs");
|
|
236
|
+
for (const f of fs.readdirSync(fromDir)) {
|
|
237
|
+
const dest = path.join(toDir, f);
|
|
238
|
+
if (!fs.existsSync(dest)) {
|
|
239
|
+
fs.mkdirSync(toDir, { recursive: true });
|
|
240
|
+
fs.copyFileSync(path.join(fromDir, f), dest);
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
function mergeIsolatedRecords(fromRoot, toRoot) {
|
|
245
|
+
let recordsMerged = 0;
|
|
246
|
+
for (const f of recordFiles(fromRoot)) {
|
|
247
|
+
const content = fs.readFileSync(path.join(fromRoot, "records", f), "utf8");
|
|
248
|
+
for (const line of content.split("\n")) {
|
|
249
|
+
const trimmed = line.trim();
|
|
250
|
+
if (trimmed === "") {
|
|
251
|
+
continue;
|
|
252
|
+
}
|
|
253
|
+
let record;
|
|
254
|
+
try {
|
|
255
|
+
record = JSON.parse(trimmed);
|
|
256
|
+
} catch {
|
|
257
|
+
continue;
|
|
258
|
+
}
|
|
259
|
+
const at = typeof record.at === "string" ? record.at : void 0;
|
|
260
|
+
if (!at) {
|
|
261
|
+
continue;
|
|
262
|
+
}
|
|
263
|
+
const dest = path.join(toRoot, "records", `${monthOf(at)}.jsonl`);
|
|
264
|
+
fs.mkdirSync(path.dirname(dest), { recursive: true });
|
|
265
|
+
fs.appendFileSync(dest, `${trimmed}
|
|
266
|
+
`);
|
|
267
|
+
recordsMerged += 1;
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
if (recordsMerged > 0) {
|
|
271
|
+
copyRecordDiffs(fromRoot, toRoot);
|
|
272
|
+
}
|
|
273
|
+
return { recordsMerged };
|
|
274
|
+
}
|
|
275
|
+
function archiveIsolatedRecords(fromRoot, toRoot, meta) {
|
|
276
|
+
const lines = [];
|
|
277
|
+
for (const f of recordFiles(fromRoot)) {
|
|
278
|
+
const content = fs.readFileSync(path.join(fromRoot, "records", f), "utf8");
|
|
279
|
+
for (const line of content.split("\n")) {
|
|
280
|
+
if (line.trim() !== "") {
|
|
281
|
+
lines.push(line);
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
if (lines.length === 0) {
|
|
286
|
+
return null;
|
|
287
|
+
}
|
|
288
|
+
const date = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
289
|
+
const dir = path.join(toRoot, "records", "archive", meta.project);
|
|
290
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
291
|
+
let dest = path.join(dir, `${date}-${meta.lane}.jsonl`);
|
|
292
|
+
let n = 2;
|
|
293
|
+
while (fs.existsSync(dest)) {
|
|
294
|
+
dest = path.join(dir, `${date}-${meta.lane}-${n}.jsonl`);
|
|
295
|
+
n += 1;
|
|
296
|
+
}
|
|
297
|
+
fs.writeFileSync(dest, `${lines.join("\n")}
|
|
298
|
+
`);
|
|
299
|
+
return dest;
|
|
300
|
+
}
|
|
216
301
|
function writeParentMarker(isolatedHome) {
|
|
217
302
|
try {
|
|
218
303
|
fs.writeFileSync(path.join(isolatedHome, PARENT_MARKER), `${globalRoot()}
|
|
@@ -230,7 +315,7 @@ function resolveParentGlobal(isolatedHome) {
|
|
|
230
315
|
}
|
|
231
316
|
return globalRoot();
|
|
232
317
|
}
|
|
233
|
-
function mergeIsolatedHome(isolatedHome) {
|
|
318
|
+
function mergeIsolatedHome(isolatedHome, meta) {
|
|
234
319
|
if (!fs.existsSync(isolatedHome)) {
|
|
235
320
|
return null;
|
|
236
321
|
}
|
|
@@ -238,7 +323,10 @@ function mergeIsolatedHome(isolatedHome) {
|
|
|
238
323
|
if (path.resolve(isolatedHome) === path.resolve(toRoot)) {
|
|
239
324
|
return null;
|
|
240
325
|
}
|
|
241
|
-
|
|
326
|
+
const learning = mergeIsolatedLearning(isolatedHome, toRoot);
|
|
327
|
+
const recordsArchivePath = archiveIsolatedRecords(isolatedHome, toRoot, meta);
|
|
328
|
+
const { recordsMerged } = mergeIsolatedRecords(isolatedHome, toRoot);
|
|
329
|
+
return { ...learning, recordsMerged, recordsArchivePath };
|
|
242
330
|
}
|
|
243
331
|
|
|
244
332
|
// src/commands/work.ts
|
|
@@ -839,12 +927,17 @@ async function runWorkDone(id, opts = {}) {
|
|
|
839
927
|
const color = makeColors(c.color);
|
|
840
928
|
let worktreeNote = null;
|
|
841
929
|
let mergeNote = null;
|
|
930
|
+
let recordsNote = null;
|
|
842
931
|
const isolatedHome = result.worktree ? path2.join(result.worktree.path, ".awl", "home") : path2.join(root, ".awl", "home");
|
|
843
932
|
try {
|
|
844
|
-
const
|
|
933
|
+
const project = loadProjectName(root) ?? path2.basename(root);
|
|
934
|
+
const merged = mergeIsolatedHome(isolatedHome, { project, lane: id });
|
|
845
935
|
if (merged && (merged.gotchasAdded > 0 || merged.rulesAdded > 0 || merged.generationsAdded > 0)) {
|
|
846
936
|
mergeNote = `\uD559\uC2B5 \uC804\uC5ED \uBCD1\uD569 gotcha ${merged.gotchasAdded} \xB7 rule ${merged.rulesAdded} \xB7 generation ${merged.generationsAdded}`;
|
|
847
937
|
}
|
|
938
|
+
if (merged && merged.recordsMerged > 0) {
|
|
939
|
+
recordsNote = `records \uC804\uC5ED \uBCD1\uD569 ${merged.recordsMerged}\uAC74${merged.recordsArchivePath ? ` \xB7 \uC544\uCE74\uC774\uBE0C ${merged.recordsArchivePath}` : ""}`;
|
|
940
|
+
}
|
|
848
941
|
} catch (e) {
|
|
849
942
|
process.stderr.write(
|
|
850
943
|
`
|
|
@@ -879,6 +972,10 @@ ${feedback(c, "ok", `\uC644\uB8CC \uCC98\uB9AC ${color.bold(id)}`, "\uC0C1\uD0D
|
|
|
879
972
|
}
|
|
880
973
|
if (mergeNote) {
|
|
881
974
|
process.stdout.write(` ${color.dim(mergeNote)}
|
|
975
|
+
`);
|
|
976
|
+
}
|
|
977
|
+
if (recordsNote) {
|
|
978
|
+
process.stdout.write(` ${color.dim(recordsNote)}
|
|
882
979
|
`);
|
|
883
980
|
}
|
|
884
981
|
}
|