e2e-agent-runner 1.0.0 → 1.0.2
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/git.mjs +19 -2
- package/package.json +1 -1
- package/runner.mjs +13 -3
package/git.mjs
CHANGED
|
@@ -41,13 +41,23 @@ export async function probeFolder(cwd) {
|
|
|
41
41
|
}
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
-
/** 실행 전 검증 — 폴더 존재·git 저장소·클린 워킹트리(사용자 미커밋 변경 보호).
|
|
44
|
+
/** 실행 전 검증 — 폴더 존재·git 저장소·클린 워킹트리(사용자 미커밋 변경 보호).
|
|
45
|
+
* dirty 거부 시 어떤 파일이 걸렸는지 목록을 에러에 포함(porcelain 행, ≤8건 표시+외 N건)
|
|
46
|
+
* — 원인 파일을 바로 알게 해 "정리"의 실행 오류를 줄인다. */
|
|
45
47
|
export async function preflight(cwd) {
|
|
46
48
|
if (!existsSync(cwd)) throw new GitError(`프로젝트 폴더가 없습니다: ${cwd}`);
|
|
47
49
|
const inside = await run(cwd, 'rev-parse', '--is-inside-work-tree');
|
|
48
50
|
if (inside !== 'true') throw new GitError('git 저장소가 아닙니다(작업 브랜치·병합 불가).');
|
|
49
51
|
const dirty = await run(cwd, 'status', '--porcelain');
|
|
50
|
-
if (dirty)
|
|
52
|
+
if (dirty) {
|
|
53
|
+
const files = dirty.split('\n').filter(Boolean).map((l) => l.trim().slice(0, 80));
|
|
54
|
+
const shown = files.slice(0, 8);
|
|
55
|
+
const more = files.length - shown.length;
|
|
56
|
+
const list = shown.join(', ') + (more > 0 ? ` 외 ${more}건` : '');
|
|
57
|
+
throw new GitError(
|
|
58
|
+
`커밋되지 않은 변경(${files.length}건)이 있어 작업을 시작할 수 없습니다 — 폴더를 정리(커밋/stash)한 뒤 다시 시도하세요. 대상: ${list}`,
|
|
59
|
+
);
|
|
60
|
+
}
|
|
51
61
|
}
|
|
52
62
|
|
|
53
63
|
export async function currentBranch(cwd) {
|
|
@@ -77,6 +87,13 @@ export function taskBranchName(taskId) {
|
|
|
77
87
|
return `e2e-task/${String(taskId).slice(0, 8)}`;
|
|
78
88
|
}
|
|
79
89
|
|
|
90
|
+
/** 작업 브랜치가 base 에 쌓은 커밋 수 — 0이면 무변경(질문·조사) 과제.
|
|
91
|
+
* 서버 상태머신이 테스트/리뷰/배포 생략(short-circuit)을 결정하는 결정론 신호다. */
|
|
92
|
+
export async function commitCount(cwd, base) {
|
|
93
|
+
const n = await run(cwd, 'rev-list', '--count', `${base}..HEAD`);
|
|
94
|
+
return Number(n) || 0;
|
|
95
|
+
}
|
|
96
|
+
|
|
80
97
|
/** 작업 브랜치 생성(있으면 체크아웃) — implement 단계 전 1회. */
|
|
81
98
|
export async function ensureTaskBranch(cwd, taskId) {
|
|
82
99
|
const branch = taskBranchName(taskId);
|
package/package.json
CHANGED
package/runner.mjs
CHANGED
|
@@ -18,7 +18,7 @@ import { dirname, join } from 'node:path';
|
|
|
18
18
|
import { api, runnerIdFromToken, sleep } from './api.mjs';
|
|
19
19
|
import { parsePhaseMarker, probeClaude, runClaude } from './claude.mjs';
|
|
20
20
|
import {
|
|
21
|
-
ensureTaskBranch, escapeTaskBranch, GitError, mergeToBase, preflight, probeFolder, taskBranchName,
|
|
21
|
+
commitCount, ensureTaskBranch, escapeTaskBranch, GitError, mergeToBase, preflight, probeFolder, taskBranchName,
|
|
22
22
|
} from './git.mjs';
|
|
23
23
|
|
|
24
24
|
// runner/.env.local 자동 로드 — 이미 설정된 env 는 덮지 않는다(셀 export 우선).
|
|
@@ -176,6 +176,8 @@ async function handleStep({ step, task, project }) {
|
|
|
176
176
|
session_id: result.sessionId ?? null,
|
|
177
177
|
error: cancelledNow ? 'cancelled' : (result.error ?? null),
|
|
178
178
|
cancelled: Boolean(cancelledNow),
|
|
179
|
+
// implement 전용 — 작업 브랜치 커밋 수(무변경 단축 신호). 다른 페이즈는 미첨부.
|
|
180
|
+
commits: result.commits,
|
|
179
181
|
usage: result.usage ?? undefined,
|
|
180
182
|
});
|
|
181
183
|
log(`단계 종결: ${task.id.slice(0, 8)}/${step.phase} → ${cancelledNow ? 'cancelled' : result.ok ? 'done' : 'fail'}`);
|
|
@@ -194,14 +196,22 @@ async function handleStep({ step, task, project }) {
|
|
|
194
196
|
}
|
|
195
197
|
|
|
196
198
|
/** implement — git 프리플라이트 → (이전 작업 브랜치 탈출) → 작업 브랜치 → claude(신규 세션).
|
|
197
|
-
* base_branch 를 서버에 보고(유실 방지: EventBuffer 가 재전송한다).
|
|
199
|
+
* base_branch 를 서버에 보고(유실 방지: EventBuffer 가 재전송한다).
|
|
200
|
+
* 종결 시 작업 브랜치의 커밋 수(base..HEAD)를 함께 보고 — 0이면 서버가 무변경 단축한다. */
|
|
198
201
|
async function runImplement({ step, task, project, buf, cancelled }) {
|
|
199
202
|
await preflight(project.folder_path);
|
|
200
203
|
const base = await escapeTaskBranch(project.folder_path);
|
|
201
204
|
const branch = await ensureTaskBranch(project.folder_path, task.id);
|
|
202
205
|
buf.taskMeta = { base_branch: base, branch };
|
|
203
206
|
log(`브랜치 준비: ${branch} (base ${base})`);
|
|
204
|
-
|
|
207
|
+
const result = await runPhase({ step, task, project, buf, cancelled, extraMeta: buf.taskMeta });
|
|
208
|
+
let commits;
|
|
209
|
+
try {
|
|
210
|
+
commits = await commitCount(project.folder_path, base);
|
|
211
|
+
} catch {
|
|
212
|
+
/* 커밋 수 계산 실패 — 미보고 시 서버는 기존 전체 파이프라인으로 동작 */
|
|
213
|
+
}
|
|
214
|
+
return { ...result, commits };
|
|
205
215
|
}
|
|
206
216
|
|
|
207
217
|
/** test/remediate/review 공통 — prompt_md + resume 세션. */
|