shuangyan-notebook/第五域 · Fifth Domain/⚒️ 铸渊·协作指令|GitHub ↔ Notion 桥接协议/🔒 铸渊补充指令|执行保护层 · 技术层不可逆性强制保障 · 系统自保护机制(ZY-LANGDRIV 54edc047533543a883b13ab25e3bd6ca.md
Guanghu Domestic Migration a27e87cb99 chore: import sanitized domestic snapshot for REPO-007
Source snapshot: 97d7f0fae96dc04b7ddad56fc1db6a108ed662cc

[SEC-CLEAN] · pre-push-clean v1.0 · 109处敏感信息已自动转乱码
2026-07-17 15:59:55 +08:00

29 KiB
Raw Blame History

belongs_to
belongs_to
INDEX · 铸渊·协作指令GitHub ↔ Notion 桥接协议

🔒 铸渊补充指令|执行保护层 · 技术层不可逆性强制保障 · 系统自保护机制ZY-LANGDRIVE-2026-0325-001-S1· 霜砚签发 · 冰朔授权


零、为什么需要执行保护层


一、执行保护层总体设计

1.1 核心原则

人类说话 → 系统接收
         ↓
    ┌─────────────────────────────────┐
    │     执行保护层Execution Guard │
    │                                 │
    │  1. 锁定执行上下文               │
    │  2. 切断外部干预通道             │
    │  3. 启动全链路原子执行           │
    │  4. 完成后解锁 + 展示结果        │
    │                                 │
    │  在此期间:                      │
    │  · 前端无取消按钮               │
    │  · API 拒绝取消/修改请求        │
    │  · Workflow 不可被手动停止       │
    │  · 数据库写入不可被中途回滚      │
    └─────────────────────────────────┘
         ↓
    执行完成 → 结果回放 → 人类看到完整过程

1.2 三层保护架构

保护层 位置 作用 实现方式
L1 · 前端隔离 交互页面(浏览器端) 不给人类干预的入口 指令发出后 UI 锁定,无取消按钮
L2 · API 拦截 后端中间层 即使绕过前端API 也拒绝干预 执行中的操作拒绝 cancel/abort 请求
L3 · 执行原子性 Workflow + 数据层 保证整条链路要么全完成,要么安全回退到执行前状态 事务锁 + 检查点 + 自动恢复

二、L1 · 前端执行隔离

2.1 指令发出后的 UI 状态切换

创建文件:docs/js/execution-guard.js

/**
 * 执行保护 · 前端隔离层
 * 
 * 当开发者发出一条会触发系统操作的指令后:
 * 1. 输入框立即禁用(不能发新指令)
 * 2. 取消/撤回按钮不存在(从未渲染过,不是隐藏)
 * 3. 界面进入「执行回放」模式
 * 4. 执行完成后才解锁输入框
 */

class ExecutionGuard {
  constructor(chatInterface) {
    this.chat = chatInterface;
    this.locked = false;
    this.executionId = null;
  }

  /**
   * 进入执行保护状态
   * 在意图路由识别到需要执行系统操作时调用
   */
  lockExecution(executionId) {
    this.locked = true;
    this.executionId = executionId;

    // 1. 禁用输入框
    this.chat.inputField.disabled = true;
    this.chat.inputField.placeholder = '⏳ 系统执行中…请等待完成';
    this.chat.sendButton.disabled = true;

    // 2. 显示执行状态条
    this.chat.showStatusBar({
      icon: '🔄',
      text: '指令已接收,系统正在执行…',
      color: 'blue',
      // 注意:没有取消按钮。这不是遗漏,是设计。
    });

    // 3. 开始轮询执行状态
    this.pollExecutionStatus(executionId);
  }

  /**
   * 轮询执行状态
   * 展示每一步的执行回放
   */
  async pollExecutionStatus(executionId) {
    const poll = async () => {
      if (!this.locked) return;

      try {
        const res = await fetch(`${API_BASE}/execution/${executionId}/status`);
        const status = await res.json();

        // 更新执行进度展示
        this.chat.updateStatusBar({
          text: status.currentStep,
          progress: status.progress, // 0-100
          steps: status.completedSteps // 已完成的步骤列表
        });

        // 逐步展示执行过程(事后回放)
        if (status.newLogs) {
          status.newLogs.forEach(log => {
            this.chat.appendSystemMessage({
              type: 'execution-log',
              icon: log.success ? '✅' : '⏳',
              text: log.message,
              timestamp: log.timestamp
            });
          });
        }

        if (status.state === 'completed') {
          this.unlockExecution(status.result);
        } else if (status.state === 'failed') {
          this.handleExecutionFailure(status.error);
        } else {
          // 继续轮询
          setTimeout(poll, 2000);
        }
      } catch (e) {
        // 网络错误不中断执行,继续轮询
        setTimeout(poll, 5000);
      }
    };

    poll();
  }

  /**
   * 执行完成,解锁界面
   */
  unlockExecution(result) {
    this.locked = false;
    this.executionId = null;

    // 1. 恢复输入框
    this.chat.inputField.disabled = false;
    this.chat.inputField.placeholder = '和铸渊说话…';
    this.chat.sendButton.disabled = false;

    // 2. 显示最终结果
    this.chat.showStatusBar({
      icon: '✅',
      text: '执行完成',
      color: 'green',
      autoHide: 5000
    });

    // 3. 铸渊用自然语言总结执行结果
    this.chat.appendMessage({
      role: 'assistant',
      content: result.reply
    });
  }

  /**
   * 执行失败处理
   * 注意:即使失败,也不是「撤回」。失败的操作会触发自动回滚到执行前状态。
   */
  handleExecutionFailure(error) {
    this.locked = false;
    this.executionId = null;

    this.chat.inputField.disabled = false;
    this.chat.inputField.placeholder = '和铸渊说话…';
    this.chat.sendButton.disabled = false;

    this.chat.showStatusBar({
      icon: '❌',
      text: '执行失败 · 系统已自动回滚到执行前状态',
      color: 'red',
      autoHide: 10000
    });

    this.chat.appendMessage({
      role: 'assistant',
      content: `❌ 操作执行失败:${error.message}\n\n系统已自动回滚到执行前的状态。没有任何数据被修改。\n你可以重新描述你想做的事或者说「发生了什么」来查看详细日志。`
    });
  }

  /**
   * 拦截浏览器关闭/刷新
   * 执行期间不允许关闭页面
   */
  setupBrowserGuard() {
    window.addEventListener('beforeunload', (e) => {
      if (this.locked) {
        e.preventDefault();
        e.returnValue = '⚠️ 系统正在执行操作,关闭页面不会中断执行,但你将无法看到执行结果。';
        return e.returnValue;
      }
    });
  }
}

module.exports = { ExecutionGuard };

2.2 CSS 执行锁定样式

创建文件:docs/css/execution-guard.css

/* 执行中状态 · 输入框锁定 */
.chat-input.execution-locked {
  opacity: 0.5;
  pointer-events: none;
  background: #f5f5f5;
  border-color: #ddd;
}

.chat-input.execution-locked::placeholder {
  color: #999;
}

/* 执行状态条 */
.execution-status-bar {
  display: flex;
  align-items: center;
  padding: 12px 16px;
  border-radius: 8px;
  margin: 8px 0;
  font-size: 14px;
  animation: pulse-gentle 2s infinite;
}

.execution-status-bar.blue {
  background: rgba(35, 131, 226, 0.08);
  color: #2383E2;
}

.execution-status-bar.green {
  background: rgba(15, 123, 108, 0.08);
  color: #0F7B6C;
  animation: none;
}

.execution-status-bar.red {
  background: rgba(212, 76, 71, 0.08);
  color: #D44C47;
  animation: none;
}

/* 执行进度条 */
.execution-progress {
  height: 3px;
  background: #E3E3E3;
  border-radius: 2px;
  margin-top: 8px;
  overflow: hidden;
}

.execution-progress-fill {
  height: 100%;
  background: #2383E2;
  border-radius: 2px;
  transition: width 0.5s ease;
}

/* 执行日志 */
.execution-log-entry {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  padding: 4px 0;
  font-size: 13px;
  color: #787774;
}

.execution-log-entry .log-icon {
  flex-shrink: 0;
}

.execution-log-entry .log-time {
  flex-shrink: 0;
  color: #B4B4B0;
  font-size: 12px;
}

/* 温和脉冲动画 */
@keyframes pulse-gentle {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.7; }
}

/* 注意:没有 .cancel-button 类。这不是遗漏。 */

三、L2 · API 执行拦截层

3.1 执行上下文锁

创建文件:backend/api-server/middleware/execution-lock.js

/**
 * 执行锁中间件
 * 
 * 当一个操作开始执行时:
 * 1. 为该操作创建一个执行上下文executionId
 * 2. 锁定相关资源(防止并发冲突)
 * 3. 拒绝一切 cancel/abort/rollback 请求
 * 4. 执行完成后自动释放锁
 * 
 * 这不是分布式锁——是单用户执行保护。
 * 同一个开发者不能同时执行多个写入操作。
 */

const crypto = require('crypto');

// 内存中的执行锁表(生产环境可迁移到 Redis
const activeLocks = new Map();

function generateExecutionId() {
  return `exec-${Date.now()}-${crypto.randomBytes(4).toString('hex')}`;
}

/**
 * 创建执行锁
 */
function acquireLock(devId, operation) {
  // 检查该开发者是否有正在执行的操作
  if (activeLocks.has(devId)) {
    const existing = activeLocks.get(devId);
    return {
      success: false,
      reply: `⏳ 你有一个操作正在执行中(${existing.operation}),请等待完成。\n\n系统不允许同时执行多个操作——这是为了保护数据一致性。`
    };
  }

  const executionId = generateExecutionId();
  const lock = {
    executionId,
    devId,
    operation,
    startTime: Date.now(),
    state: 'running',
    steps: [],
    checkpoints: []
  };

  activeLocks.set(devId, lock);

  return {
    success: true,
    executionId,
    lock
  };
}

/**
 * 释放执行锁
 */
function releaseLock(devId) {
  activeLocks.delete(devId);
}

/**
 * 获取执行状态
 */
function getExecutionStatus(executionId) {
  for (const [devId, lock] of activeLocks) {
    if (lock.executionId === executionId) {
      return lock;
    }
  }
  return null;
}

/**
 * 记录执行步骤(用于事后回放)
 */
function logStep(devId, step) {
  const lock = activeLocks.get(devId);
  if (lock) {
    lock.steps.push({
      ...step,
      timestamp: new Date().toISOString()
    });
  }
}

/**
 * 保存检查点(用于失败时回滚)
 */
function saveCheckpoint(devId, checkpoint) {
  const lock = activeLocks.get(devId);
  if (lock) {
    lock.checkpoints.push({
      ...checkpoint,
      timestamp: new Date().toISOString()
    });
  }
}

/**
 * 取消拦截中间件
 * 拦截所有试图取消执行中操作的请求
 */
function blockCancellation(req, res, next) {
  const devId = req.user?.devId;
  if (!devId) return next();

  // 如果请求是 cancel/abort 类型
  if (req.path.includes('/cancel') || 
      req.path.includes('/abort') || 
      req.path.includes('/rollback') ||
      req.method === 'DELETE' && activeLocks.has(devId)) {
    
    const lock = activeLocks.get(devId);
    if (lock && lock.state === 'running') {
      return res.status(423).json({
        success: false,
        locked: true,
        executionId: lock.executionId,
        reply: [
          `🔒 操作「${lock.operation}」正在执行中,不可取消。`,
          ``,
          `系统已接收你的指令并开始执行。这条执行链路涉及多个自动化流程的联动,`,
          `中途中断会导致数据不一致和级联故障。`,
          ``,
          `⏳ 请等待执行完成。完成后你会看到完整的执行结果。`,
          ``,
          `如果你对结果不满意,可以说「前面的没想好,我们重新来」——`,
          `系统会在已有结果的基础上重新迭代,而不是撤回已执行的操作。`
        ].join('\n')
      });
    }
  }

  next();
}

module.exports = {
  acquireLock,
  releaseLock,
  getExecutionStatus,
  logStep,
  saveCheckpoint,
  blockCancellation
};

3.2 执行状态查询接口

创建文件:backend/api-server/routes/execution.js

const express = require('express');
const router = express.Router();
const { getExecutionStatus } = require('../middleware/execution-lock');
const { requireAuth } = require('../middleware/auth');

router.use(requireAuth);

// 查询执行状态(前端轮询用)
router.get('/:executionId/status', async (req, res) => {
  const status = getExecutionStatus(req.params.executionId);

  if (!status) {
    return res.json({
      state: 'not_found',
      reply: '未找到该执行记录。可能已经完成。'
    });
  }

  // 计算进度百分比
  const progress = status.steps.length > 0
    ? Math.min(95, (status.completedSteps / status.totalSteps) * 100)
    : 5; // 刚开始至少显示 5%

  res.json({
    executionId: status.executionId,
    state: status.state,
    operation: status.operation,
    progress: Math.round(progress),
    currentStep: status.steps.length > 0 
      ? status.steps[status.steps.length - 1].message 
      : '初始化执行环境…',
    completedSteps: status.steps.filter(s => s.success).map(s => ({
      message: s.message,
      timestamp: s.timestamp
    })),
    newLogs: status.steps.slice(req.query.after || 0),
    startTime: new Date(status.startTime).toISOString(),
    elapsed: Date.now() - status.startTime
  });
});

// 注意:没有 DELETE /:executionId 接口。没有取消接口。这不是遗漏。
// 也没有 POST /:executionId/cancel。也没有 POST /:executionId/abort。
// 因为执行一旦开始,不可中断。

module.exports = router;

四、L3 · 执行原子性保障

4.1 核心思想

4.2 检查点系统

创建文件:backend/api-server/services/checkpoint.js

/**
 * 检查点系统
 * 
 * 在执行链路的每个关键节点保存快照。
 * 如果后续步骤失败,自动回滚到最近的成功检查点。
 * 
 * 检查点包含:
 * - Notion 数据库的变更前快照
 * - GitHub 操作前的 commit SHA
 * - 执行到哪一步
 */

const { saveCheckpoint: saveLockCheckpoint } = require('../middleware/execution-lock');

class CheckpointManager {
  constructor(devId, executionId) {
    this.devId = devId;
    this.executionId = executionId;
    this.checkpoints = [];
  }

  /**
   * 在执行关键操作前保存检查点
   */
  async save(label, snapshotData) {
    const checkpoint = {
      id: `cp-${this.checkpoints.length + 1}`,
      label,
      data: snapshotData,
      timestamp: new Date().toISOString()
    };

    this.checkpoints.push(checkpoint);
    saveLockCheckpoint(this.devId, checkpoint);

    return checkpoint.id;
  }

  /**
   * 回滚到指定检查点
   * 按逆序撤销检查点之后的所有操作
   */
  async rollbackTo(checkpointId) {
    const targetIndex = this.checkpoints.findIndex(cp => cp.id === checkpointId);
    if (targetIndex === -1) throw new Error(`检查点 ${checkpointId} 不存在`);

    // 从最后一个检查点开始逆序回滚
    const toRollback = this.checkpoints.slice(targetIndex + 1).reverse();

    for (const cp of toRollback) {
      try {
        await this.rollbackCheckpoint(cp);
      } catch (e) {
        // 回滚失败 → 记录到审计日志 → 需要人工介入
        console.error(`检查点 ${cp.id} 回滚失败:`, e.message);
        await this.escalateToAdmin(cp, e);
      }
    }

    // 截断检查点列表
    this.checkpoints = this.checkpoints.slice(0, targetIndex + 1);
  }

  /**
   * 回滚单个检查点
   */
  async rollbackCheckpoint(checkpoint) {
    const { data } = checkpoint;

    switch (data.type) {
      case 'notion_write':
        // 如果是新建的页面 → 删除(归档)
        if (data.action === 'create') {
          await notionClient.archivePage(data.pageId);
        }
        // 如果是更新的页面 → 恢复原值
        else if (data.action === 'update') {
          await notionClient.updatePage(data.pageId, data.previousValues);
        }
        break;

      case 'github_workflow':
        // Workflow 无法直接回滚,但可以触发一个 revert workflow
        if (data.revertWorkflow) {
          await githubClient.triggerWorkflow(data.revertWorkflow, {
            original_run_id: data.runId,
            reason: 'auto_rollback'
          });
        }
        break;

      case 'github_file':
        // 恢复文件到之前的内容
        if (data.previousSha) {
          await githubClient.revertFile(data.path, data.previousSha);
        } else {
          await githubClient.deleteFile(data.path, 'auto_rollback');
        }
        break;

      default:
        console.warn(`未知检查点类型: ${data.type}`);
    }
  }

  /**
   * 回滚失败时上报管理员
   */
  async escalateToAdmin(checkpoint, error) {
    // 写入 SYSLOG
    await notionClient.createSyslog({
      content: `⚠️ 自动回滚失败 | 执行ID: ${this.executionId} | 检查点: ${checkpoint.label} | 错误: ${error.message}`,
      type: '紧急',
      devId: 'SYSTEM'
    });

    // 通知霜砚(通过 Notion 维护日志)
    await notionClient.createMaintenanceLog({
      title: `[紧急] 自动回滚失败 · ${this.executionId}`,
      type: '系统异常',
      detail: `检查点 ${checkpoint.id} (${checkpoint.label}) 回滚失败: ${error.message}。需要冰朔人工介入。`
    });
  }
}

module.exports = { CheckpointManager };

4.3 原子执行包装器

创建文件:backend/api-server/services/atomic-executor.js

/**
 * 原子执行器
 * 
 * 包装所有写入操作,确保:
 * 1. 执行前保存检查点
 * 2. 执行中记录每一步
 * 3. 执行失败自动回滚
 * 4. 执行完成释放锁
 * 
 * 使用方式:
 * const executor = new AtomicExecutor(devId);
 * await executor.execute('创建工单', async (ctx) => {
 *   await ctx.step('写入Notion', async () => { ... });
 *   await ctx.step('触发Workflow', async () => { ... });
 * });
 */

const { acquireLock, releaseLock, logStep } = require('../middleware/execution-lock');
const { CheckpointManager } = require('./checkpoint');
const { auditLog } = require('../middleware/audit');

class AtomicExecutor {
  constructor(devId) {
    this.devId = devId;
  }

  async execute(operationName, fn) {
    // 1. 获取执行锁
    const lockResult = acquireLock(this.devId, operationName);
    if (!lockResult.success) {
      return lockResult; // 返回锁冲突信息
    }

    const { executionId, lock } = lockResult;
    const checkpoint = new CheckpointManager(this.devId, executionId);

    // 2. 保存初始检查点
    await checkpoint.save('执行前状态', {
      type: 'initial',
      timestamp: new Date().toISOString()
    });

    // 3. 执行上下文
    const ctx = {
      executionId,

      // 执行单步操作
      step: async (stepName, stepFn) => {
        logStep(this.devId, {
          message: `⏳ ${stepName}...`,
          success: false
        });

        try {
          const result = await stepFn();

          logStep(this.devId, {
            message: `✅ ${stepName}`,
            success: true
          });

          return result;
        } catch (e) {
          logStep(this.devId, {
            message: `❌ ${stepName}: ${e.message}`,
            success: false
          });
          throw e; // 向上抛出,触发回滚
        }
      },

      // 保存检查点
      checkpoint: async (label, data) => {
        return await checkpoint.save(label, data);
      }
    };

    // 4. 执行主逻辑
    try {
      const result = await fn(ctx);

      // 5. 成功:更新锁状态 + 释放
      lock.state = 'completed';
      lock.result = result;

      // 延迟释放锁(给前端时间拉取最终状态)
      setTimeout(() => releaseLock(this.devId), 10000);

      return {
        success: true,
        executionId,
        ...result
      };

    } catch (e) {
      // 6. 失败:自动回滚
      lock.state = 'rolling_back';
      logStep(this.devId, {
        message: '🔄 执行失败,正在自动回滚...',
        success: false
      });

      try {
        await checkpoint.rollbackTo('cp-1'); // 回滚到初始状态
        logStep(this.devId, {
          message: '✅ 已回滚到执行前状态',
          success: true
        });
      } catch (rollbackError) {
        logStep(this.devId, {
          message: `⚠️ 回滚异常:${rollbackError.message},已通知管理员`,
          success: false
        });
      }

      lock.state = 'failed';
      lock.error = { message: e.message };

      setTimeout(() => releaseLock(this.devId), 10000);

      return {
        success: false,
        executionId,
        error: e.message,
        reply: `❌ 操作「${operationName}」执行失败:${e.message}\n\n系统已自动回滚到执行前状态没有数据被修改。`
      };
    }
  }
}

module.exports = { AtomicExecutor };

五、GitHub Actions 保护

5.1 Workflow 并发锁

对于由语言驱动触发的 workflow在 workflow 文件中加入并发控制:

# 在所有语言驱动触发的 workflow 中添加:
concurrency:
  group: lang-drive-$ github.event.inputs.dev_id -$ github.event.inputs.module 
  cancel-in-progress: false  # 关键:不允许取消正在执行的

5.2 API 层屏蔽 Workflow 取消

在后端中间层中,不暴露 GitHub Actions 的 cancel 接口:

// backend/api-server/routes/execution.js 中追加:

// 明确拒绝取消 workflow 的请求
router.post('/:executionId/cancel', (req, res) => {
  res.status(403).json({
    success: false,
    reply: [
      '🔒 执行中的操作不可取消。',
      '',
      '系统已开始执行90+ 个自动化流程正在联动。',
      '中途中断会导致数据不一致和级联故障。',
      '',
      '请等待执行完成。如果结果不理想,你可以说:',
      '「前面的我没想好,我们重新来」',
      '系统会在已有基础上重新迭代。'
    ].join('\n')
  });
});

router.delete('/:executionId', (req, res) => {
  res.status(403).json({
    success: false,
    reply: '🔒 不可删除执行记录。所有执行都是永久记录。'
  });
});

六、超时保护 + 死锁防护

6.1 执行超时处理

创建文件:backend/api-server/services/execution-watchdog.js

/**
 * 执行看门狗
 * 
 * 定期检查执行锁是否超时。
 * 如果一个操作执行超过 MAX_EXECUTION_TIME标记为超时并释放锁。
 * 这是防止死锁的兜底机制。
 */

const { releaseLock } = require('../middleware/execution-lock');

// 最大执行时间15 分钟(大部分操作应该在 2 分钟内完成)
const MAX_EXECUTION_TIME = 15 * 60 * 1000;

// 警告时间10 分钟
const WARN_TIME = 10 * 60 * 1000;

function startWatchdog(activeLocks) {
  setInterval(() => {
    const now = Date.now();

    for (const [devId, lock] of activeLocks) {
      if (lock.state !== 'running') continue;

      const elapsed = now - lock.startTime;

      // 超时:强制释放
      if (elapsed > MAX_EXECUTION_TIME) {
        console.error(`[WATCHDOG] 执行超时: ${lock.executionId} (${lock.operation}) - ${Math.round(elapsed/1000)}s`);
        
        lock.state = 'timeout';
        lock.error = { message: `执行超时(超过 ${MAX_EXECUTION_TIME/60000} 分钟)` };

        // 写入紧急 SYSLOG
        writeSyslog({
          content: `⚠️ 执行超时 | ${lock.executionId} | ${lock.operation} | 开发者: ${devId} | 已运行 ${Math.round(elapsed/1000)}s`,
          type: '紧急'
        });

        // 延迟释放(给前端时间获取超时状态)
        setTimeout(() => releaseLock(devId), 30000);
      }
      // 警告
      else if (elapsed > WARN_TIME && !lock.warned) {
        console.warn(`[WATCHDOG] 执行时间较长: ${lock.executionId} (${lock.operation}) - ${Math.round(elapsed/1000)}s`);
        lock.warned = true;
      }
    }
  }, 30000); // 每 30 秒检查一次
}

module.exports = { startWatchdog, MAX_EXECUTION_TIME };

七、文件创建清单

新增文件清单

// 前端 · 执行保护 UI
docs/js/execution-guard.js               前端执行隔离UI锁定 + 回放
docs/css/execution-guard.css             执行锁定样式

// 后端 · 执行锁
backend/api-server/middleware/execution-lock.js   执行上下文锁 + 取消拦截
backend/api-server/routes/execution.js            执行状态查询接口

// 后端 · 原子执行
backend/api-server/services/checkpoint.js         检查点系统快照+回滚
backend/api-server/services/atomic-executor.js    原子执行包装器

// 后端 · 看门狗
backend/api-server/services/execution-watchdog.js  超时保护 + 死锁防护

八、与 LANGDRIVE 主指令的关系

本补充指令的文件与 LANGDRIVE Phase 3-6 的文件无冲突

  • Phase 3 的写入接口(routes/write.js)调用 AtomicExecutor 来执行写入
  • Phase 4 的意图路由(middleware/intent-router.js)在识别到写入意图后,先通过 ExecutionGuard 锁定前端
  • Phase 5 的权限检查(middleware/auth.js)在执行锁之前运行——权限不够直接拒绝,不进入执行保护
  • Phase 6 的认知引导在预览站沙箱中运行,沙箱操作同样受执行保护(培养开发者的习惯)

集成顺序:权限检查 → 沙箱检查 → 执行锁获取 → 检查点保存 → 原子执行 → 释放锁 → 结果回放


九、验收标准

  • 开发者发出写入指令后,前端输入框立即锁定,无取消按钮
  • 执行期间API 层拒绝所有 cancel/abort 请求,返回友好提示
  • 执行成功:锁释放,前端解锁,展示完整执行结果
  • 执行失败:自动回滚到执行前状态,通知开发者
  • 回滚失败:自动上报管理员(写入 SYSLOG + 维护日志)
  • 执行超时(>15分钟看门狗自动释放锁 + 标记异常
  • 同一开发者不能同时执行多个写入操作
  • 浏览器关闭/刷新时提示「执行中,关闭不会中断」
  • GitHub Actions 的 cancel-in-progress: false 已设置
  • 所有执行记录永久保留,不可删除

十、回执要求

[ZY-LANGDRIVE-S1-RECEIPT]
指令编号: ZY-LANGDRIVE-2026-0325-001-S1
补充内容: Phase 7 · 执行保护层

前端隔离L1:
  UI锁定: /
  无取消按钮: /
  执行回放: /

API拦截L2:
  执行锁: /
  取消拦截: /
  并发防护: /

原子执行L3:
  检查点系统: /
  自动回滚: /
  超时看门狗: /

集成测试:
  写入指令锁定执行解锁: /
  执行失败自动回滚: /
  取消请求被拦截: /

🔗 签发霜砚AG-SY-01

👤 授权冰朔TCS-0002∞

📅 日期2026-03-25

📌 版权:国作登字-2026-A-00037559

🔗 父指令ZY-LANGDRIVE-2026-0325-001