@angar2/taskery 1.0.2 → 1.0.3
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/bin/finish.js +15 -1
- package/bin/lib.js +1 -0
- package/bin/orche.js +16 -4
- package/bin/prepare.js +19 -4
- package/package.json +1 -1
package/bin/finish.js
CHANGED
|
@@ -286,6 +286,15 @@ function writeChangelog(main, st, goal) {
|
|
|
286
286
|
return file;
|
|
287
287
|
}
|
|
288
288
|
|
|
289
|
+
// orca worktree rm 뒤 폴더가 사라지기를 기다리는 최대 시간
|
|
290
|
+
const ORCA_RM_WAIT_MS = 30 * 1000;
|
|
291
|
+
|
|
292
|
+
// 경로가 사라질 때까지 기다린다(최대 ms)
|
|
293
|
+
function waitGone(p, ms) {
|
|
294
|
+
const until = Date.now() + ms;
|
|
295
|
+
while (fs.existsSync(p) && Date.now() < until) Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, 200);
|
|
296
|
+
}
|
|
297
|
+
|
|
289
298
|
// 워크트리·브랜치 정리 — 커밋 안 된 변경이 있으면 남기고, 브랜치는 병합된 것만 지운다.
|
|
290
299
|
// force는 prune에서 사용자가 확인했을 때만 — 병합 안 된 브랜치도 지운다(복구 명령 출력)
|
|
291
300
|
function cleanup(main, st, { force = false } = {}) {
|
|
@@ -307,6 +316,8 @@ function cleanup(main, st, { force = false } = {}) {
|
|
|
307
316
|
try {
|
|
308
317
|
execFileSync('orca', ['worktree', 'rm', '--worktree', `path:${st.worktree}`, '--json'], { stdio: ['ignore', 'pipe', 'pipe'] });
|
|
309
318
|
notes.push(`Orca 워크트리를 지웠다: ${st.worktree}`);
|
|
319
|
+
// Orca는 답한 뒤에도 뒤에서 폴더를 지우고 병합된 브랜치도 함께 지운다 — 폴더가 사라질 때까지 기다린 뒤 브랜치를 본다
|
|
320
|
+
waitGone(st.worktree, ORCA_RM_WAIT_MS);
|
|
310
321
|
} catch (e) {
|
|
311
322
|
notes.push(`Orca 워크트리를 지우지 못해 남겼다: ${((e.stderr || '') + '').trim() || e.message}`);
|
|
312
323
|
branchFree = false;
|
|
@@ -325,7 +336,10 @@ function cleanup(main, st, { force = false } = {}) {
|
|
|
325
336
|
}
|
|
326
337
|
if (!merged && !force) notes.push(`브랜치 ${st.branch}는 부모에 병합되지 않아 남겼다.`);
|
|
327
338
|
else if (!branchFree || L.currentBranch(main) === st.branch) notes.push(`브랜치 ${st.branch}를 지우지 못해 남겼다(사용 중).`);
|
|
328
|
-
else if (L.git(main, ['branch', merged ? '-d' : '-D', st.branch], { allowFail: true }) === null)
|
|
339
|
+
else if (L.git(main, ['branch', merged ? '-d' : '-D', st.branch], { allowFail: true }) === null) {
|
|
340
|
+
// 그 사이 Orca가 지웠으면 실패가 아니다
|
|
341
|
+
notes.push(L.branchExists(main, st.branch) ? `브랜치 ${st.branch}를 지우지 못해 남겼다.` : `브랜치 ${st.branch}가 지워졌다. 복구: git branch ${st.branch} ${tip}`);
|
|
342
|
+
}
|
|
329
343
|
else notes.push(`브랜치 ${st.branch}를 지웠다. 복구: git branch ${st.branch} ${tip}`);
|
|
330
344
|
return notes;
|
|
331
345
|
}
|
package/bin/lib.js
CHANGED
package/bin/orche.js
CHANGED
|
@@ -10,6 +10,8 @@ const WAIT_MS = Number(process.env.TASKERY_WAIT_REPORTS_MS) || 60 * 60 * 1000;
|
|
|
10
10
|
const POLL_MS = Math.min(1000, WAIT_MS);
|
|
11
11
|
// 첫 지시문을 보낸 뒤 턴 시작을 지켜보는 시간(orca terminal send --wait-submit)
|
|
12
12
|
const SUBMIT_WAIT_SEC = 30;
|
|
13
|
+
// 턴 시작 미관측 뒤 Enter를 보내고 화면을 읽기 전 기다리는 시간
|
|
14
|
+
const SCREEN_SETTLE_MS = 2000;
|
|
13
15
|
|
|
14
16
|
function reportsFile(main) {
|
|
15
17
|
return path.join(main, '.taskery', 'reports.log');
|
|
@@ -197,13 +199,23 @@ async function orcaDispatchTask(ctx, a) {
|
|
|
197
199
|
if (r.refused) L.fail(`orca-dispatch-task: ${label} 탭(${handle})이 첫 지시문을 받지 않았다 — ${r.refused}\n${manual}`);
|
|
198
200
|
return r.observed;
|
|
199
201
|
};
|
|
200
|
-
// 턴
|
|
202
|
+
// Orca가 턴 시작을 관측했다고 답해도 지시문이 입력창에 제출되지 않은 채 남은 적이 있다(stash TASK-105).
|
|
203
|
+
// 그래서 관측 여부와 무관하게 Enter만 한 번 더 보낸다 — 입력창이 비었거나 이미 진행 중이면 영향이 없다
|
|
204
|
+
const observed = send();
|
|
201
205
|
let sendNote = null;
|
|
202
|
-
|
|
206
|
+
try {
|
|
207
|
+
orca(['terminal', 'send', '--terminal', handle, '--enter']);
|
|
208
|
+
} catch (e) {
|
|
209
|
+
if (observed) sendNote = `확인용 Enter를 보내지 못했다(${e.message}) — 탭에서 진행을 확인한다.`;
|
|
210
|
+
else L.fail(`orca-dispatch-task: ${label} 탭(${handle})에서 첫 지시문의 턴 시작이 관측되지 않았고, Enter도 보내지 못했다 — ${e.message}\n'orca terminal read --terminal ${handle}'로 화면을 읽어, 지시문이 입력창에 남아 있으면 Enter를, 없으면 아래 첫 지시문을 보낸다.\n--- 첫 지시문 ---\n${text}`);
|
|
211
|
+
}
|
|
212
|
+
// 관측되지 않았으면 화면을 본다 — 지시문이 보이면 Enter로 들어간 것이고, 없으면 준비 전에 사라진 것이라 한 번 더 보낸다
|
|
213
|
+
if (!observed) {
|
|
214
|
+
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, SCREEN_SETTLE_MS);
|
|
203
215
|
if (onScreen(handle, text.split('\n')[0].split(' ').slice(0, 4).join(' '))) {
|
|
204
|
-
sendNote = '턴
|
|
216
|
+
sendNote = '턴 시작이 관측되지 않아 Enter를 한 번 더 보냈고, 탭 화면에 첫 지시문이 보인다 — 탭에서 진행을 확인한다.';
|
|
205
217
|
} else if (send()) {
|
|
206
|
-
sendNote = '첫 전송은 턴 시작이 관측되지 않고 화면에도 없어 한 번 더 보냈다.';
|
|
218
|
+
sendNote = '첫 전송은 턴 시작이 관측되지 않고 Enter 뒤 화면에도 없어 한 번 더 보냈다.';
|
|
207
219
|
} else {
|
|
208
220
|
L.fail(`orca-dispatch-task: ${label} 탭(${handle})에 첫 지시문을 두 번 보냈지만 턴 시작이 관측되지 않았다.\n${manual}`);
|
|
209
221
|
}
|
package/bin/prepare.js
CHANGED
|
@@ -218,12 +218,26 @@ async function installPackages(dir) {
|
|
|
218
218
|
return [`npm ci 실패(${took}) — 워크트리에서 직접 설치한다(${dir}):\n${L.tail(r.out, 15)}`];
|
|
219
219
|
}
|
|
220
220
|
|
|
221
|
-
// PLAN.md
|
|
222
|
-
function
|
|
221
|
+
// PLAN.md `## 태스크 목록` 절에서 항목 줄을 찾는다. 다른 절의 번호 목록(목표 등)은 보지 않는다. 없으면 멈춘다
|
|
222
|
+
function itemLine(main, plan, item) {
|
|
223
223
|
const file = path.join(main, '.taskery', 'plans', plan, 'PLAN.md');
|
|
224
224
|
const lines = fs.readFileSync(file, 'utf8').split('\n');
|
|
225
|
-
const
|
|
226
|
-
|
|
225
|
+
const fenced = L.fenceMask(lines);
|
|
226
|
+
const start = lines.findIndex((l, i) => !fenced[i] && l.trim() === '## 태스크 목록');
|
|
227
|
+
let idx = -1;
|
|
228
|
+
for (let i = start + 1; start !== -1 && i < lines.length && !(!fenced[i] && /^## /.test(lines[i])); i++) {
|
|
229
|
+
if (!fenced[i] && new RegExp(`^\\s*${item}\\.\\s`).test(lines[i])) {
|
|
230
|
+
idx = i;
|
|
231
|
+
break;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
if (idx === -1) L.fail(`prepare-task: ${plan}/PLAN.md \`## 태스크 목록\`에 항목 ${item}이 없다. 목록 형식은 '${item}. <한 줄 설명> — 선행: <항목 번호들 또는 없음>'이다.`);
|
|
235
|
+
return { file, lines, idx };
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
// 항목 줄 끝에 태스크 번호를 붙인다(`--item`)
|
|
239
|
+
function linkItem(main, plan, item, label) {
|
|
240
|
+
const { file, lines, idx } = itemLine(main, plan, item);
|
|
227
241
|
const linked = lines[idx].match(/TASK-\d+/g) || [];
|
|
228
242
|
lines[idx] = `${lines[idx].replace(/\s+$/, '')} (${label})`;
|
|
229
243
|
fs.writeFileSync(file, lines.join('\n'));
|
|
@@ -236,6 +250,7 @@ async function prepareTask(ctx, a) {
|
|
|
236
250
|
const rule = L.readGitRule(main);
|
|
237
251
|
const switches = validate(a, rule);
|
|
238
252
|
const plan = resolvePlan(main, a.plan);
|
|
253
|
+
if (a.item != null) itemLine(main, plan, a.item); // 브랜치·워크트리를 만들기 전에 확인한다
|
|
239
254
|
const noBranch = !!a['no-branch'];
|
|
240
255
|
const noWorktree = noBranch || !!a['no-worktree'];
|
|
241
256
|
const parent = checkMain(main);
|