feat(engine): implement state persistence, failure reason tracking, and quality scoring as per Astra review

This commit is contained in:
g1nation
2026-05-04 15:39:01 +09:00
parent 16106327b8
commit 817d76c3fa
2 changed files with 72 additions and 0 deletions
+36
View File
@@ -1,4 +1,6 @@
import * as vscode from 'vscode';
import * as fs from 'fs';
import * as path from 'path';
import { lockManager } from '../core/lock';
import { actionQueue } from '../core/queue';
import { logInfo, logError } from '../utils';
@@ -61,6 +63,7 @@ export class MissionState {
private _stage: PipelineStage = 'idle';
private _auditTrail: AuditEntry[] = [];
private _lastTransitionTime: number = Date.now();
private _failureReason?: string;
public readonly missionId: string;
public readonly startTime: number;
@@ -96,8 +99,35 @@ export class MissionState {
this._lastTransitionTime = now;
logInfo(`[MissionState] ${this.missionId}: ${entry.from}${entry.to} (${entry.durationFromPrev}ms) — ${message}`);
this.saveToDisk();
}
/**
* 진행 상태를 디스크에 영구적으로 기록합니다 (State Save).
* 크래시 발생 시 어디까지 진행되었는지 파악하는 기초 데이터가 됩니다.
*/
private saveToDisk(): void {
try {
const workspacePath = vscode.workspace.workspaceFolders?.[0]?.uri.fsPath || '';
if (!workspacePath) return;
const astraDir = path.join(workspacePath, '.astra', 'missions');
if (!fs.existsSync(astraDir)) {
fs.mkdirSync(astraDir, { recursive: true });
}
const filePath = path.join(astraDir, `${this.missionId}.json`);
fs.writeFileSync(filePath, JSON.stringify(this.toStructuredLog(), null, 2), 'utf-8');
} catch (err) {
logError(`[MissionState] Failed to save state to disk for ${this.missionId}`, err);
}
}
public setFailureReason(reason: string): void {
this._failureReason = reason;
this.saveToDisk();
}
/**
* 전체 미션의 경과 시간을 반환합니다.
*/
@@ -137,6 +167,7 @@ export class MissionState {
status: this._stage,
startTime: new Date(this.startTime).toISOString(),
totalElapsedMs: this.getElapsedMs(),
failureReason: this._failureReason,
transitionCount: this._auditTrail.length,
transitions: this._auditTrail.map(e => ({
from: e.from,
@@ -385,6 +416,11 @@ export class AgentEngine {
this.transition('error', `오류 발생: ${error.message}`, onProgress);
// 실패 원인 명시적 기록 (Astra 피드백: Record failure reason)
if (this.state) {
this.state.setFailureReason(`[${type}] ${rule.description} - 세부원인: ${error.message}`);
}
// Error Recovery Matrix 기반 세분화된 로깅
switch (type) {
case ErrorType.ABORT: