result-tracker.js 4.2 KB
/**
 * ResultTracker - 跟踪多轮执行结果和验证状态
 *
 * 职责:
 * - 累积各轮次的 agent 执行结果
 * - 状态机校验:防止状态退化(如 DONE → ERROR)
 * - 保留历史轨迹供调试
 * - 查询全局验证状态(哪些 validator 已通过/未通过)
 * - 判断整体任务是否完成
 */

const { Scheduler } = require('./scheduler');

/**
 * Agent 状态转换合法性矩阵
 * key: `${agentType}:${oldStatus}→${newStatus}`
 * value: 'allow' | 'warn' | 'deny'
 *
 * 未列出的转换默认 'allow'
 */
const STATE_TRANSITIONS = {
  // executor: DONE 不应退化为 ERROR(任务已完成,不应回滚)
  'executor:DONE→ERROR': 'warn',
  // validator: PASS 退化为 FAIL 需要 warn(可能是重新验证后失败)
  'validator:PASS→FAIL': 'warn',
  // 正常的修复链路
  'executor:ERROR→DONE': 'allow',
  'validator:FAIL→PASS': 'allow',
};

class ResultTracker {
  /**
   * @param {Object} agents - Agent 配置 { name: { type, ... } }
   */
  constructor(agents) {
    this.agents = agents;
    this._results = new Map();
    /** 历史轨迹:记录每次状态变更 */
    this._history = [];
  }

  /**
   * 合并一轮执行结果(带状态机检查)
   * @param {Array<{agent, status, message, output}>} results
   * @param {number} [loop] - 当前循环轮次(用于历史记录)
   */
  merge(results, loop) {
    for (const r of results) {
      this._mergeOne(r, loop);
    }
  }

  /**
   * 合并单个结果(内部方法)
   * @private
   */
  _mergeOne(result, loop) {
    const { agent, status } = result;
    const agentType = this.agents[agent]?.type || 'unknown';
    const existing = this._results.get(agent);
    const oldStatus = existing?.status || null;

    // 状态机检查
    if (oldStatus) {
      const transitionKey = `${agentType}:${oldStatus}→${status}`;
      const rule = STATE_TRANSITIONS[transitionKey] || 'allow';

      if (rule === 'warn') {
        console.warn(
          `[ResultTracker] ⚠️ 状态退化: ${agent} (${agentType}) ${oldStatus} → ${status}。` +
          `允许覆盖但记录告警。`
        );
      }
      // 'deny' 暂不启用:线上更安全的做法是 warn + 覆盖,而非阻断
    }

    // 记录历史
    this._history.push({
      agent,
      agentType,
      oldStatus,
      newStatus: status,
      message: result.message,
      loop: loop || null,
      timestamp: Date.now(),
    });

    // 覆盖写入
    this._results.set(agent, result);
  }

  /**
   * 手动设置某个 agent 的结果
   */
  set(agent, result) {
    this._mergeOne(result);
  }

  /** 获取所有累积结果 */
  getAll() {
    return Array.from(this._results.values());
  }

  /** 是否还没有任何结果 */
  isEmpty() {
    return this._results.size === 0;
  }

  /** 任务是否完成(所有 validator PASS + 所有 executor DONE) */
  isComplete() {
    return Scheduler.isComplete(this.agents, this.getAll());
  }

  /**
   * 获取历史轨迹
   * @param {string} [agentName] - 可选,过滤特定 Agent
   * @returns {Array<{agent, agentType, oldStatus, newStatus, message, loop, timestamp}>}
   */
  getHistory(agentName) {
    if (agentName) {
      return this._history.filter(h => h.agent === agentName);
    }
    return [...this._history];
  }

  // ── 验证状态查询 ──

  /** 所有配置的 validator 名称 */
  get allValidators() {
    return Object.entries(this.agents)
      .filter(([_, cfg]) => cfg.type === 'validator')
      .map(([name]) => name);
  }

  /** 已通过的 validator */
  get passedValidators() {
    const all = this.getAll();
    return this.allValidators.filter(name =>
      all.find(r => r.agent === name && r.status === 'PASS')
    );
  }

  /** 未通过的 validator */
  get unpassedValidators() {
    const all = this.getAll();
    return this.allValidators.filter(name =>
      !all.find(r => r.agent === name && r.status === 'PASS')
    );
  }

  // ── Agent 类型查询 ──

  /** 所有配置的 executor / orchestrator 名称 */
  get allExecutors() {
    return Object.entries(this.agents)
      .filter(([_, cfg]) => cfg.type === 'executor' || cfg.type === 'orchestrator')
      .map(([name]) => name);
  }
}

module.exports = { ResultTracker };