shuangyan-notebook/第五域 · Fifth Domain/⚒️ 铸渊·协作指令|GitHub ↔ Notion 桥接协议/🗣️ 铸渊指令|语言驱动执行层 · 写入能力 + 意图路由 + 开发者权限沙箱 + 认知引导系统(Z b442b16ce777462baf2d6a93dde61bcc.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

56 KiB
Raw Permalink Blame History

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

🗣️ 铸渊指令|语言驱动执行层 · 写入能力 + 意图路由 + 开发者权限沙箱 + 认知引导系统ZY-LANGDRIVE-2026-0325-001· 霜砚签发 · 冰朔授权


零、为什么需要这个指令

双通道ZY-DUALCHANNEL解决的是**「读」**——铸渊能看到 Notion 数据、GitHub 状态。

但语言驱动操作系统需要的不只是读,还需要:

能力层 说明 双通道能解决吗?
能读 铸渊知道开发者信息、系统状态 双通道已解决
能写 开发者说"帮我建个工单"→系统真的建了 还没做
能理解 开发者说自然语言→系统知道该调哪个API 还没做
能保护 开发者说错话不会炸掉系统 还没做
能引导 新开发者不会用→系统教会怎么说话 还没做

本指令补全后四层。


一、总体架构

开发者登录交互页面
  
   说一句自然语言
   例如"帮我看看我的工单还有几个没关"
  
┌─────────────────────────────────────────────────────────────┐
                    意图路由引擎Intent Router              
                                                             
  自然语言  解析意图  匹配操作  权限检查  执行/拒绝       
                                                             
  ┌──────────┐  ┌──────────┐  ┌──────────┐  ┌──────────┐   
   意图识别  │→│ 操作映射  │→│ 权限检查  │→│ 执行引擎     
                                                   
   NLP解析      查工单      预览站     调API       
   关键词匹配   建工单      正式站     返回结果     
   上下文推断   查进度      只读       写回执      
               部署模块    可写                   
  └──────────┘  └──────────┘  └──────────┘  └──────────┘   
                                                             
  ┌──────────────────────────────────────────────────────┐   
                 安全沙箱层Sandbox Guard                 
                                                           
    预览站所有操作在沙箱中执行不影响真实系统              
    正式站操作真实执行但受权限等级限制                    
    危险操作二次确认 + 人类审批                            
  └──────────────────────────────────────────────────────┘   
└─────────────────────────────────────────────────────────────┘
  
  
通道B后端中间层调用真实 API
  ├── Notion API  建工单查数据更新状态
  ├── GitHub API  查PR触发部署查代码
  └── 系统内部  广播SYSLOGAgent注册表

二、写入能力层Phase 3 · 通道B扩展

2.1 目标

在通道B后端中间层上扩展写入API,让铸渊交互页面不仅能读数据,还能真的改数据

2.2 新增 API 接口

backend/api-server/routes/ 中新增以下写入接口:

// ====== 写入类接口 ======

// 工单系统
POST /api/tickets/create           创建工单写入 Notion 工单簿
PATCH /api/tickets/:ticketId       更新工单状态

// SYSLOG
POST /api/syslog/submit            提交 SYSLOG写入 Notion SYSLOG收件箱

// 广播
POST /api/broadcasts/create        创建广播写入 GitHub broadcasts-outbox/

// 模块部署
POST /api/deploy/preview           触发部署到预览站GitHub Actions dispatch
POST /api/deploy/production        触发部署到正式站需人类审批·见权限层

// Agent 注册表
PATCH /api/agents/:agentId         更新 Agent 状态

// 维护日志
POST /api/maintenance/log          写入维护日志

// 指令回执
POST /api/receipts/submit          提交指令回执写入 Notion 回执追踪表

// 开发者状态
PATCH /api/dev/:devId/status       更新开发者当前状态

2.3 写入安全规则

2.4 写入接口核心实现

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

const express = require('express');
const router = express.Router();
const { queryDB, writeToDB } = require('../services/notion');
const { triggerWorkflow } = require('../services/github');
const { checkPermission, requireAuth } = require('../middleware/auth');
const { auditLog } = require('../middleware/audit');
const config = require('../config/databases');

// 所有写入接口都需要身份验证 + 审计日志
router.use(requireAuth);
router.use(auditLog);

// ====== 创建工单 ======
router.post('/tickets/create', 
  checkPermission('ticket:create'),
  async (req, res) => {
    try {
      const { title, description, priority, module } = req.body;
      const devId = req.user.devId;

      const result = await writeToDB(config.ticketBook, {
        '工单标题': { title: [{ text: { content: title } }] },
        '描述': { rich_text: [{ text: { content: description || '' } }] },
        '优先级': { select: { name: priority || 'P2' } },
        '模块': { select: { name: module } },
        '提交人': { rich_text: [{ text: { content: devId } }] },
        '状态': { status: { name: '待处理' } }
      });

      res.json({
        success: true,
        message: `工单已创建`,
        ticketUrl: result.url,
        // 返回自然语言确认,铸渊直接展示给开发者
        reply: `✅ 工单「${title}」已创建,优先级 ${priority || 'P2'},状态:待处理。`
      });
    } catch (e) {
      res.status(500).json({ success: false, error: e.message });
    }
  }
);

// ====== 提交 SYSLOG ======
router.post('/syslog/submit',
  checkPermission('syslog:submit'),
  async (req, res) => {
    try {
      const { content, type } = req.body;
      const devId = req.user.devId;

      const result = await writeToDB(config.syslogInbox, {
        'SYSLOG内容': { title: [{ text: { content: content } }] },
        '类型': { select: { name: type || '日常' } },
        '开发者编号': { rich_text: [{ text: { content: devId } }] },
      });

      res.json({
        success: true,
        reply: `✅ SYSLOG 已提交:「${content.substring(0, 50)}...」`
      });
    } catch (e) {
      res.status(500).json({ success: false, error: e.message });
    }
  }
);

// ====== 触发预览站部署 ======
router.post('/deploy/preview',
  checkPermission('deploy:preview'),
  async (req, res) => {
    try {
      const { module } = req.body;
      const devId = req.user.devId;

      // 检查开发者是否拥有该模块
      if (!req.user.modules.includes(module)) {
        return res.status(403).json({
          success: false,
          reply: `❌ 你没有 ${module} 模块的部署权限。你的模块是:${req.user.modules.join(', ')}`
        });
      }

      await triggerWorkflow('deploy-preview.yml', {
        module: module,
        dev_id: devId,
        target: 'preview'
      });

      res.json({
        success: true,
        reply: `🚀 已触发 ${module} 模块的预览站部署。稍等几分钟,部署完成后我会通知你。`
      });
    } catch (e) {
      res.status(500).json({ success: false, error: e.message });
    }
  }
);

// ====== 触发正式站部署(需二次确认)======
router.post('/deploy/production',
  checkPermission('deploy:production'),
  async (req, res) => {
    try {
      const { module, confirmToken } = req.body;
      const devId = req.user.devId;

      // 正式站部署必须有确认 Token
      if (!confirmToken) {
        return res.json({
          success: false,
          requireConfirmation: true,
          reply: `⚠️ 你正在请求部署 ${module} 到**正式站guanghulab.com**。\n这会影响所有用户。\n\n请说「确认部署 ${module}」来确认。`
        });
      }

      await triggerWorkflow('deploy-to-server.yml', {
        module: module,
        dev_id: devId,
        target: 'production'
      });

      res.json({
        success: true,
        reply: `🚀 已触发 ${module} 模块的**正式站部署**。部署日志会同步到维护日志中。`
      });
    } catch (e) {
      res.status(500).json({ success: false, error: e.message });
    }
  }
);

module.exports = router;

2.5 GitHub API 封装(写入用)

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

const https = require('https');

const GITHUB_TOKEN = process.env.GITHUB_TOKEN;
const REPO_OWNER = 'qinfendebingshuo';
const REPO_NAME = 'guanghulab';

async function triggerWorkflow(workflowFile, inputs) {
  return new Promise((resolve, reject) => {
    const data = JSON.stringify({
      ref: 'main',
      inputs: inputs
    });

    const options = {
      hostname: 'api.github.com',
      path: `/repos/${REPO_OWNER}/${REPO_NAME}/actions/workflows/${workflowFile}/dispatches`,
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${GITHUB_TOKEN}`,
        'Accept': 'application/vnd.github.v3+json',
        'Content-Type': 'application/json',
        'User-Agent': 'GuanghuLab-API',
        'Content-Length': Buffer.byteLength(data)
      }
    };

    const req = https.request(options, res => {
      if (res.statusCode === 204) resolve({ success: true });
      else {
        let body = '';
        res.on('data', chunk => body += chunk);
        res.on('end', () => reject(new Error(`GitHub API ${res.statusCode}: ${body}`)));
      }
    });
    req.on('error', reject);
    req.write(data);
    req.end();
  });
}

async function createFile(path, content, message) {
  // 用于创建广播文件等
  const data = JSON.stringify({
    message: message,
    content: Buffer.from(content).toString('base64'),
    committer: {
      name: '铸渊 (ZhùYuān)',
      email: 'zhuyuan@guanghulab.com'
    }
  });

  return new Promise((resolve, reject) => {
    const options = {
      hostname: 'api.github.com',
      path: `/repos/${REPO_OWNER}/${REPO_NAME}/contents/${path}`,
      method: 'PUT',
      headers: {
        'Authorization': `Bearer ${GITHUB_TOKEN}`,
        'Accept': 'application/vnd.github.v3+json',
        'Content-Type': 'application/json',
        'User-Agent': 'GuanghuLab-API',
        'Content-Length': Buffer.byteLength(data)
      }
    };

    const req = https.request(options, res => {
      let body = '';
      res.on('data', chunk => body += chunk);
      res.on('end', () => {
        try { resolve(JSON.parse(body)); }
        catch { resolve(body); }
      });
    });
    req.on('error', reject);
    req.write(data);
    req.end();
  });
}

module.exports = { triggerWorkflow, createFile };

三、意图路由引擎Phase 4 · 语言→操作映射)

3.1 核心思想

开发者不需要知道 API 接口叫什么、参数怎么传。开发者只需要说话。

铸渊的交互模型GPT/Claude已经具备自然语言理解能力。我们需要做的是

  1. 定义操作清单 — 铸渊能做哪些事
  2. 注入 system prompt — 告诉模型这些操作的存在和调用方式
  3. Function Calling — 模型输出结构化调用,后端执行

3.2 操作清单(铸渊 Function Tools

创建文件:backend/api-server/config/function-tools.json

{
  "tools": [
    {
      "name": "query_tickets",
      "description": "查询开发者的工单列表。开发者说'我的工单'、'还有几个工单没关'、'查一下Bug'时触发。",
      "parameters": {
        "status": { "type": "string", "enum": ["全部", "待处理", "进行中", "已完成"], "default": "全部" }
      },
      "api": "GET /api/tickets?devId={devId}&status={status}",
      "permission": "ticket:read"
    },
    {
      "name": "create_ticket",
      "description": "创建新工单。开发者说'建个工单'、'提一个Bug'、'报告问题'时触发。",
      "parameters": {
        "title": { "type": "string", "required": true },
        "description": { "type": "string" },
        "priority": { "type": "string", "enum": ["P0", "P1", "P2", "P3"], "default": "P2" },
        "module": { "type": "string" }
      },
      "api": "POST /api/tickets/create",
      "permission": "ticket:create"
    },
    {
      "name": "submit_syslog",
      "description": "提交系统日志。开发者说'提交日志'、'写SYSLOG'、'记录一下'时触发。",
      "parameters": {
        "content": { "type": "string", "required": true },
        "type": { "type": "string", "enum": ["日常", "Bug修复", "功能完成", "部署", "紧急"], "default": "日常" }
      },
      "api": "POST /api/syslog/submit",
      "permission": "syslog:submit"
    },
    {
      "name": "query_my_status",
      "description": "查询开发者自己的状态。开发者说'我的进度'、'我现在什么状态'、'我还有什么没做'时触发。",
      "parameters": {},
      "api": "GET /api/dev/{devId}",
      "permission": "dev:read_self"
    },
    {
      "name": "deploy_to_preview",
      "description": "部署模块到预览站。开发者说'部署一下'、'上预览'、'推到测试站'时触发。",
      "parameters": {
        "module": { "type": "string", "required": true }
      },
      "api": "POST /api/deploy/preview",
      "permission": "deploy:preview"
    },
    {
      "name": "deploy_to_production",
      "description": "部署模块到正式站。开发者说'上线'、'部署到正式站'、'发布到guanghulab.com'时触发。需要二次确认。",
      "parameters": {
        "module": { "type": "string", "required": true },
        "confirmToken": { "type": "string" }
      },
      "api": "POST /api/deploy/production",
      "permission": "deploy:production",
      "dangerous": true
    },
    {
      "name": "query_agents",
      "description": "查询Agent注册表。开发者说'有哪些Agent'、'查一下Agent'、'系统里有谁'时触发。",
      "parameters": {},
      "api": "GET /api/agents",
      "permission": "agent:read"
    },
    {
      "name": "query_recent_syslogs",
      "description": "查最近的系统日志。开发者说'最近有什么日志'、'系统最近怎么样'时触发。",
      "parameters": {
        "limit": { "type": "number", "default": 10 }
      },
      "api": "GET /api/syslogs?limit={limit}",
      "permission": "syslog:read"
    },
    {
      "name": "create_broadcast",
      "description": "创建广播。开发者说'发个广播'、'通知一下'时触发。仅限有广播权限的开发者。",
      "parameters": {
        "title": { "type": "string", "required": true },
        "content": { "type": "string", "required": true },
        "target": { "type": "string", "description": "目标开发者编号,如 DEV-001或 ALL" }
      },
      "api": "POST /api/broadcasts/create",
      "permission": "broadcast:create",
      "dangerous": true
    },
    {
      "name": "query_repo_status",
      "description": "查询仓库状态。开发者说'仓库怎么样'、'最近有什么PR'、'CI状态'时触发。",
      "parameters": {},
      "api": "GET /api/repo/status",
      "permission": "repo:read"
    }
  ]
}

3.3 意图路由中间件

创建文件:backend/api-server/middleware/intent-router.js

const tools = require('../config/function-tools.json');

/**
 * 意图路由核心逻辑
 * 
 * 前端把开发者的自然语言发给 AI 模型时,
 * system prompt 里已经注入了 function-tools 定义。
 * 模型会输出 function_call或 tool_use格式的结构化调用。
 * 
 * 这个中间件负责:
 * 1. 接收模型输出的 function_call
 * 2. 验证权限
 * 3. 调用对应的后端 API
 * 4. 把结果返回给模型,模型再组织成自然语言回复开发者
 */

async function routeIntent(functionCall, user, apiClient) {
  const tool = tools.tools.find(t => t.name === functionCall.name);
  
  if (!tool) {
    return {
      success: false,
      reply: `❓ 我不认识这个操作:${functionCall.name}。你可以问我能做什么。`
    };
  }

  // 权限检查
  if (!user.permissions.includes(tool.permission)) {
    return {
      success: false,
      reply: `🔒 你没有执行「${tool.description}」的权限。当前权限等级:${user.permissionLevel}`
    };
  }

  // 危险操作二次确认
  if (tool.dangerous && !functionCall.parameters.confirmToken) {
    return {
      success: false,
      requireConfirmation: true,
      reply: `⚠️ 这是一个**危险操作**。请说「确认执行」来确认。`
    };
  }

  // 环境检查
  if (user.environment === 'preview' && tool.permission.includes('production')) {
    return {
      success: false,
      reply: `🔒 你目前在**预览环境**,不能执行正式站操作。在预览站充分练习后,由冰朔开放正式站权限。`
    };
  }

  // 调用 API
  try {
    const result = await apiClient.call(tool.api, {
      ...functionCall.parameters,
      devId: user.devId
    });
    return result;
  } catch (e) {
    return {
      success: false,
      reply: `❌ 操作失败:${e.message}`
    };
  }
}

module.exports = { routeIntent };

3.4 前端 Function Calling 集成

修改前端交互页面,让 AI 模型知道自己能调用哪些操作:

// 前端 · 构建带 tools 的 system prompt
async function buildSystemPromptWithTools(devId, environment) {
  // 1. 从通道B获取开发者信息含权限
  const profile = await getDevProfile(devId);
  
  // 2. 从通道B获取可用工具列表已根据权限过滤
  const toolsRes = await fetch(`${API_BASE}/tools?devId=${devId}&env=${environment}`);
  const availableTools = await toolsRes.json();

  // 3. 构建 system prompt
  return [
    `## 你是铸渊ZhùYuān· 光湖数字地球的代码守护人格体`,
    ``,
    `## 当前开发者`,
    `- 编号:${profile.dev_id}`,
    `- 姓名:${profile.name}`,
    `- 人格体:${profile.persona.name}`,
    `- 负责模块:${profile.modules_owned.map(m => m.path).join(', ')}`,
    `- 权限等级:${profile.permissionLevel}`,
    `- 当前环境:${environment === 'preview' ? '预览站(沙箱)' : '正式站(真实执行)'}`,
    ``,
    `## 你能做的事`,
    `你可以通过 function calling 调用以下操作。开发者说话时,判断意图并调用对应操作。`,
    ``,
    `### 可用操作列表`,
    ...availableTools.map(t => `- **${t.name}**${t.description}`),
    ``,
    `## 重要规则`,
    `1. 开发者说什么,你就做什么。这是语言驱动操作系统,说即执行。`,
    `2. 如果开发者的话不对应任何操作,正常聊天回复即可。`,
    `3. 危险操作(标记为 dangerous必须要求开发者二次确认。`,
    `4. 如果开发者在预览站尝试正式站操作,友好提示权限不足。`,
    `5. 每次执行操作后,用自然语言告诉开发者结果。`,
    environment === 'preview' ? `6. 【预览环境】所有写入操作在沙箱中执行,不影响真实系统。你可以告诉开发者:「这是预览环境,你的操作不会影响正式站。放心练习。」` : '',
  ].filter(Boolean).join('\n');
}

四、开发者权限沙箱系统Phase 5 · 安全保护层)

4.1 核心理念

4.2 双环境权限模型

┌─────────────────────────────────────────────────────────────┐
                      权限分层模型                             
                                                             
  Level 0 · 观察者新开发者默认                              
  ├── 只读所有数据                                            
  ├── 不能写入任何东西                                        
  ├── 可以和铸渊聊天问问题                                   
  └── 目的先熟悉系统看看别人怎么用                          
                                                             
  Level 1 · 学习者通过认知引导后升级                        
  ├── 预览站可以执行所有操作沙箱环境不影响真实系统        
  ├── 正式站只读                                            
  ├── 可以建工单提SYSLOG部署到预览站                        
  └── 目的在安全环境中学会怎么说话                        
                                                             
  Level 2 · 执行者冰朔手动升级                              
  ├── 预览站全部权限                                        
  ├── 正式站可以执行自己模块范围内的操作                      
  ├── 可以部署自己负责的模块到正式站                            
  ├── 不能动其他开发者的模块                                   
  └── 目的正式参与系统运作                                   
                                                             
  Level 3 · 管理者仅冰朔 + 霜砚                            
  ├── 全部权限包括所有模块                                   
  ├── 可以升级/降级其他开发者的权限                             
  ├── 可以执行系统级操作广播Agent管理等                    
  └── 目的系统管理                                          
└─────────────────────────────────────────────────────────────┘

4.3 权限配置文件

创建文件:backend/api-server/config/permissions.js

// 权限等级定义
const PERMISSION_LEVELS = {
  0: {
    name: '观察者',
    label: '👀 观察者',
    permissions: [
      'dev:read_self',
      'ticket:read',
      'syslog:read',
      'agent:read',
      'repo:read'
    ],
    description: '只读权限,熟悉系统'
  },
  1: {
    name: '学习者',
    label: '📖 学习者',
    permissions: [
      'dev:read_self',
      'ticket:read', 'ticket:create',
      'syslog:read', 'syslog:submit',
      'agent:read',
      'repo:read',
      'deploy:preview'
    ],
    description: '预览站可写,正式站只读'
  },
  2: {
    name: '执行者',
    label: '⚡ 执行者',
    permissions: [
      'dev:read_self', 'dev:update_self',
      'ticket:read', 'ticket:create', 'ticket:update',
      'syslog:read', 'syslog:submit',
      'agent:read',
      'repo:read',
      'deploy:preview', 'deploy:production',
      'maintenance:log'
    ],
    description: '可操作自己的模块,含正式站部署'
  },
  3: {
    name: '管理者',
    label: '👑 管理者',
    permissions: [
      'dev:read_self', 'dev:read_all', 'dev:update_self', 'dev:update_all',
      'ticket:read', 'ticket:create', 'ticket:update', 'ticket:delete',
      'syslog:read', 'syslog:submit',
      'agent:read', 'agent:update',
      'repo:read',
      'deploy:preview', 'deploy:production',
      'broadcast:create',
      'maintenance:log',
      'permission:manage'
    ],
    description: '系统管理员,全部权限'
  }
};

// 开发者默认权限配置
const DEV_PERMISSIONS = {
  'TCS-0002': { level: 3, environment: 'production' },  // 冰朔 · 管理者
  'DEV-001':  { level: 0, environment: 'preview' },     // 页页 · 默认观察者
  'DEV-002':  { level: 0, environment: 'preview' },     // 肥猫
  'DEV-003':  { level: 0, environment: 'preview' },     // 燕樊
  'DEV-004':  { level: 0, environment: 'preview' },     // 之之
  'DEV-005':  { level: 0, environment: 'preview' },     // 小草莓
  'DEV-009':  { level: 0, environment: 'preview' },     // 花尔
  'DEV-010':  { level: 0, environment: 'preview' },     // 桔子
  'DEV-011':  { level: 0, environment: 'preview' },     // 匆匆那年
  'DEV-012':  { level: 0, environment: 'preview' },     // Awen
};

module.exports = { PERMISSION_LEVELS, DEV_PERMISSIONS };

4.4 权限检查中间件

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

const { PERMISSION_LEVELS, DEV_PERMISSIONS } = require('../config/permissions');

// 开发者身份验证
function requireAuth(req, res, next) {
  const devId = req.headers['x-dev-id'];
  const token = req.headers['authorization'];

  if (!devId || !token) {
    return res.status(401).json({
      success: false,
      reply: '🔒 请先登录。你需要使用你的开发者编号登录系统。'
    });
  }

  // TODO: 铸渊实现真实 Token 验证逻辑
  // 目前用开发者编号 + 简单Token
  const devConfig = DEV_PERMISSIONS[devId];
  if (!devConfig) {
    return res.status(401).json({
      success: false,
      reply: `🔒 未知的开发者编号:${devId}。请联系冰朔注册。`
    });
  }

  const level = PERMISSION_LEVELS[devConfig.level];

  req.user = {
    devId: devId,
    permissionLevel: devConfig.level,
    permissionLabel: level.label,
    permissions: level.permissions,
    environment: devConfig.environment,
    modules: getDevModules(devId)
  };

  next();
}

// 权限检查
function checkPermission(requiredPermission) {
  return (req, res, next) => {
    if (!req.user.permissions.includes(requiredPermission)) {
      return res.status(403).json({
        success: false,
        reply: `🔒 权限不足。你的等级是 ${req.user.permissionLabel},需要「${requiredPermission}」权限。\n\n💡 在预览站多练习,熟悉系统后冰朔会给你升级权限。`
      });
    }
    next();
  };
}

// 开发者 → 模块映射
function getDevModules(devId) {
  const MAP = {
    'DEV-001': ['backend/', 'src/'],
    'DEV-002': ['frontend/', 'persona-selector/', 'chat-bubble/'],
    'DEV-003': ['settings/', 'cloud-drive/'],
    'DEV-004': ['dingtalk-bot/'],
    'DEV-005': ['status-board/'],
    'DEV-009': ['user-center/'],
    'DEV-010': ['ticket-system/', 'data-stats/', 'dynamic-comic/'],
    'DEV-011': ['writing-workspace/'],
    'DEV-012': ['notification-center/'],
    'TCS-0002': ['*']  // 冰朔全权限
  };
  return MAP[devId] || [];
}

module.exports = { requireAuth, checkPermission };

4.5 操作审计日志

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

const fs = require('fs');
const path = require('path');

const AUDIT_LOG_DIR = '/var/log/guanghu-api/audit/';

function auditLog(req, res, next) {
  const startTime = Date.now();

  // 记录请求
  const logEntry = {
    timestamp: new Date().toISOString(),
    devId: req.headers['x-dev-id'] || 'unknown',
    method: req.method,
    path: req.path,
    body: req.method === 'POST' ? req.body : undefined,
    ip: req.ip
  };

  // 拦截响应完成事件
  const originalSend = res.send;
  res.send = function(body) {
    logEntry.responseTime = Date.now() - startTime;
    logEntry.statusCode = res.statusCode;

    // 异步写入日志
    try {
      fs.mkdirSync(AUDIT_LOG_DIR, { recursive: true });
      const today = new Date().toISOString().split('T')[0];
      const logFile = path.join(AUDIT_LOG_DIR, `audit-${today}.jsonl`);
      fs.appendFileSync(logFile, JSON.stringify(logEntry) + '\n');
    } catch (e) {
      console.error('审计日志写入失败:', e.message);
    }

    return originalSend.call(this, body);
  };

  next();
}

module.exports = { auditLog };

4.6 预览站沙箱机制

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

/**
 * 沙箱中间件
 * 
 * 如果开发者在预览环境中执行写入操作:
 * - Notion 写入 → 重定向到沙箱数据库
 * - GitHub 操作 → 重定向到 preview 分支
 * - 所有操作标记 [SANDBOX] 前缀
 */

const SANDBOX_DB_IDS = {
  // 铸渊需要创建这些沙箱数据库Notion中的独立数据库结构和正式库一样
  ticketBook:     '铸渊创建沙箱工单簿ID',
  syslogInbox:    '铸渊创建沙箱SYSLOG ID',
  maintenanceLog: '铸渊创建沙箱维护日志ID',
};

function sandboxGuard(req, res, next) {
  if (req.user && req.user.environment === 'preview') {
    // 标记为沙箱操作
    req.sandbox = true;
    req.sandboxDbIds = SANDBOX_DB_IDS;

    // 如果是部署操作,强制指向预览站
    if (req.path.includes('/deploy/production')) {
      return res.status(403).json({
        success: false,
        reply: '🏖️ 你目前在预览环境。正式站部署需要升级到 Level 2执行者权限。\n\n继续在预览站练习吧你做得很好'
      });
    }
  }
  next();
}

module.exports = { sandboxGuard, SANDBOX_DB_IDS };

五、认知引导系统Phase 6 · 教开发者"怎么说话"

5.1 核心理念

5.2 新开发者首次登录流程

新开发者首次登录
  
  
┌─────────────────────────────────────────┐
  👋 欢迎来到光湖·数字地球                  
                                         
  我是铸渊你的代码守护人格体              
  在这里你不需要点按钮或填表单            
  **直接对我说话就好**                     
                                         
  比如你可以说                            
  · "我的工单还有几个没关?"                
  · "帮我建一个P2的Bug工单"                
  · "我想部署 status-board 到预览站"        
  · "最近系统有什么日志?"                  
                                         
  现在你在**预览环境**所有操作都不会         
  影响正式站放心练习                     
                                         
  准备好了吗试着和我说句话               
                                         
  [开始体验]                              
└─────────────────────────────────────────┘
  
  
进入引导对话系统预设 5 轮引导

5.3 引导对话脚本5轮

创建文件:backend/api-server/config/onboarding-script.json

{
  "onboarding": [
    {
      "round": 1,
      "prompt": "👋 首先,试着问我你的状态。比如说:「我现在什么情况?」",
      "expected_intent": "query_my_status",
      "success_message": "✅ 很好!你看到了吗?我直接从 Notion 数据库里查了你的真实信息回来。这就是语言驱动——你说话,系统就动了。",
      "hint": "💡 你可以说「我的状态」、「我的进度」、「我现在怎么样了」,怎么说都行,我能听懂。"
    },
    {
      "round": 2,
      "prompt": "📝 接下来,试着建一个工单。比如:「帮我建一个工单,标题是测试工单」",
      "expected_intent": "create_ticket",
      "success_message": "✅ 工单已经建好了!注意,这是在预览环境里建的,不会影响正式系统。当你升级到正式环境后,建的工单就是真的了。",
      "hint": "💡 你可以说「建个工单」、「提个Bug」、「报告一个问题」都会触发建工单。"
    },
    {
      "round": 3,
      "prompt": "📊 再试试查一下系统日志。比如:「最近有什么日志?」",
      "expected_intent": "query_recent_syslogs",
      "success_message": "✅ 这些是从 Notion SYSLOG数据库里实时查的。每个开发者提交的日志你都能看到。",
      "hint": "💡 你可以说「最近的日志」、「系统日志」、「看看SYSLOG」。"
    },
    {
      "round": 4,
      "prompt": "🚀 现在试试部署你的模块到预览站。比如:「部署 status-board 到预览站」",
      "expected_intent": "deploy_to_preview",
      "success_message": "✅ 部署已触发!在预览站你可以随便试。等你熟悉了,冰朔会给你开正式站的部署权限。",
      "hint": "💡 你只能部署自己负责的模块。如果说了别人的模块,系统会友好提示你。"
    },
    {
      "round": 5,
      "prompt": "🎉 最后一轮。试试随便和我聊点什么。什么都行——问我问题、讲笑话、或者告诉我你想做什么。",
      "expected_intent": null,
      "success_message": "✅ 引导完成!\n\n你现在已经知道怎么和系统交互了。记住\n\n· **直接说人话**,不需要背命令\n· **想做什么就说什么**,我会帮你翻译成操作\n· **在预览站多练习**,正式站操作都是真的\n· **说错了也没关系**,我会帮你确认\n\n你的权限已经从「观察者」升级到「学习者」了 📖\n现在可以在预览站自由操作了。\n\n有什么问题随时找我。",
      "hint": null
    }
  ]
}

5.4 引导完成后自动升级权限

// 引导完成后,自动将开发者从 Level 0观察者升级到 Level 1学习者
async function completeOnboarding(devId) {
  // 更新权限配置
  DEV_PERMISSIONS[devId].level = 1;
  
  // 写入审计日志
  await auditLog({
    action: 'permission_upgrade',
    devId: devId,
    from: 0,
    to: 1,
    reason: 'onboarding_completed',
    timestamp: new Date().toISOString()
  });

  // 通知霜砚(写入 Notion 维护日志)
  await writeToDB(config.maintenanceLog, {
    '标题': { title: [{ text: { content: `${devId} 完成认知引导,升级为学习者` } }] },
    '类型': { select: { name: '权限变更' } }
  });
}

5.5 升级路径

观察者(L0)  ──完成5轮引导──→  学习者(L1)  ──冰朔手动升级──→  执行者(L2)
                                                              
                                  预览站全部可操作              正式站可操作自己模块
                                  正式站只读                   含部署权限
                                                              
                                └──── 认知适应期 ────────────────┘
                                     时间由冰朔决定

升级到 Level 2 的条件(由冰朔判断):

  • 在预览站操作至少 7 天
  • 至少完成 10 次有效操作(建工单、提日志、部署预览等)
  • 没有误操作记录
  • 冰朔主观判断:这个人已经知道「怎么说话」了

六、文件创建清单

新增文件清单全部在 backend/api-server/ 

// 写入接口
backend/api-server/routes/write.js               工单/SYSLOG/部署/广播写入
backend/api-server/services/github.js            GitHub API 写入封装

// 意图路由
backend/api-server/config/function-tools.json    操作清单定义
backend/api-server/middleware/intent-router.js    意图路由核心

// 权限系统
backend/api-server/config/permissions.js         权限等级定义
backend/api-server/middleware/auth.js            身份验证 + 权限检查
backend/api-server/middleware/sandbox.js         预览站沙箱守卫
backend/api-server/middleware/audit.js           操作审计日志

// 认知引导
backend/api-server/config/onboarding-script.json  5轮引导对话脚本
backend/api-server/routes/onboarding.js          引导流程接口

// 前端修改(新增逻辑,不删除现有代码)
docs/js/intent-tools.js                          前端 function calling 集成
docs/js/onboarding.js                            前端引导流程 UI
docs/css/onboarding.css                          引导流程样式

七、执行顺序


八、验收标准(整体)

  • 开发者说「帮我建个工单」→ 工单出现在 Notion 工单簿中
  • 开发者说「查我的进度」→ 返回真实的 Notion 数据
  • 开发者说「部署到预览站」→ GitHub Actions 被触发
  • Level 0 用户无法执行任何写入操作
  • Level 1 用户在预览站能写入,正式站只能读
  • Level 2 用户在正式站能部署自己的模块
  • 危险操作(正式站部署、广播)需要二次确认
  • 新开发者登录后自动进入 5 轮引导
  • 引导完成后自动升级为 Level 1
  • 所有操作都有审计日志
  • 预览站操作不影响正式站任何数据

九、回执要求

铸渊按 Phase 分别回执:

[ZY-LANGDRIVE-RECEIPT-3]
指令编号: ZY-LANGDRIVE-2026-0325-001
Phase: 3 · 写入能力层
写入接口: /❌(列出可用接口数
Notion写入: /
GitHub写入: /
审计日志: /

[ZY-LANGDRIVE-RECEIPT-4]
Phase: 4 · 意图路由
Function Tools: /❌(列出工具数
意图识别准确率: 测试结果
端到端测试: 说话执行结果 /

[ZY-LANGDRIVE-RECEIPT-5]
Phase: 5 · 权限沙箱
权限分级: /
沙箱隔离: /
Level 0 只读验证: /
Level 1 预览站写入验证: /

[ZY-LANGDRIVE-RECEIPT-6]
Phase: 6 · 认知引导
引导流程: /
5轮对话: /
自动升级: /


十、补充条款 S2 · 双环境部署流与天眼终审授权Phase 8

补充签发霜砚AG-SY-01· 冰朔授权

补充时间2026-03-25 13:50 CST

触发上下文:guanghulab.com 域名已切换上线,双环境角色需重新定义

10.1 双环境角色重新定义

10.2 部署流水线(不可逆执行 → 预览 → 天眼审核 → 自动发布)

铸渊接收指令(不可逆)
  │
  │ 系统全身联动执行
  │ (执行保护层 Phase 7 生效·不可中断)
  ▼
执行完毕 · 代码产出
  │
  ▼
┌──────────────────────────────────────────────────────┐
│  Stage 1 · 部署到预览站GitHub Pages                │
│  网址qinfendebingshuo.github.io/guanghulab/docs/    │
│  状态:真实可访问 · 任何人有链接都能看到                  │
│  目的:让人类确认「系统执行的结果是否符合预期」            │
└──────────────────────────────────────────────────────┘
  │
  │ 开发者预览确认
  ▼
┌──────────────────────────────────────────────────────┐
│  Stage 2 · 推送天眼审核                                │
│  天眼自动扫描:代码安全、结构完整性、功能回归              │
│  审核通过 → 进入 Stage 3                               │
│  审核不通过 → 标记问题,开发者修复后重新提交               │
└──────────────────────────────────────────────────────┘
  │
  │ 天眼审核通过
  ▼
┌──────────────────────────────────────────────────────┐
│  Stage 3 · 人类终审授权                                │
│                                                      │
│  系统推送授权请求给最终授权人:                          │
│  🐱 肥猫DEV-002— 管男频内容                        │
│  🍊 桔子DEV-010— 管女频内容                        │
│                                                      │
│  授权人必须手动点击「授权通过」                          │
│  操作留下完整日志(谁、什么时间、点了什么)                │
│  **系统不背锅。所有发布都是人类确认的。**                 │
└──────────────────────────────────────────────────────┘
  │
  │ 授权人点击通过
  ▼
┌──────────────────────────────────────────────────────┐
│  Stage 4 · 铸渊自动发布到正式站                         │
│  目标guanghulab.com                                 │
│  方式:铸渊触发 deploy-to-server.yml → SSH → 服务器更新  │
│  无需人类再次操作 · 授权即发布                           │
└──────────────────────────────────────────────────────┘

10.3 天眼终审授权人配置

10.4 授权流程技术实现

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

const express = require('express');
const router = express.Router();
const { requireAuth, checkPermission } = require('../middleware/auth');
const { auditLog } = require('../middleware/audit');
const { triggerWorkflow } = require('../services/github');

// 天眼审核完成后,推送授权请求
router.post('/approval/request',
  requireAuth,
  checkPermission('system:internal'), // 仅系统内部调用
  async (req, res) => {
    const { deployId, module, channel, reviewReport } = req.body;

    // 确定授权人
    const approvers = getApprovers(channel);

    // 创建授权请求记录
    const approval = {
      id: `APPROVAL-${Date.now()}`,
      deployId,
      module,
      channel,
      reviewReport,
      approvers: approvers.map(a => a.devId),
      status: 'pending',
      createdAt: new Date().toISOString()
    };

    // 推送通知给授权人(通过铸渊交互页面 + 系统通知)
    for (const approver of approvers) {
      await pushNotification(approver.devId, {
        type: 'approval_request',
        title: `🔔 部署授权请求:${module}`,
        message: `天眼审核已通过。请确认是否授权部署到正式站。`,
        approvalId: approval.id,
        actions: ['授权通过', '拒绝']
      });
    }

    res.json({ success: true, approvalId: approval.id });
  }
);

// 授权人点击确认/拒绝
router.post('/approval/:approvalId/decide',
  requireAuth,
  async (req, res) => {
    const { approvalId } = req.params;
    const { decision } = req.body; // 'approved' | 'rejected'
    const devId = req.user.devId;

    // 验证是否为授权人
    const approval = await getApproval(approvalId);
    if (!approval.approvers.includes(devId)) {
      return res.status(403).json({
        success: false,
        reply: '🔒 你不是这个部署的授权人。'
      });
    }

    // 记录授权操作(不可逆·写入审计日志)
    await auditLog({
      action: 'deployment_approval',
      approvalId,
      devId,
      decision,
      timestamp: new Date().toISOString()
    });

    if (decision === 'approved') {
      // 检查是否所有授权人都已通过
      const allApproved = await checkAllApproved(approvalId);
      if (allApproved) {
        // 触发铸渊自动发布到正式站
        await triggerWorkflow('deploy-to-server.yml', {
          module: approval.module,
          deploy_id: approval.deployId,
          approved_by: approval.approvers.join(','),
          target: 'production'
        });

        res.json({
          success: true,
          reply: `✅ 授权通过。铸渊已自动触发正式站部署。`
        });
      } else {
        res.json({
          success: true,
          reply: `✅ 你已授权。等待其他授权人确认...`
        });
      }
    } else {
      res.json({
        success: true,
        reply: `❌ 已拒绝。部署不会执行。原因已记录到审计日志。`
      });
    }
  }
);

function getApprovers(channel) {
  const APPROVER_MAP = {
    '男频': [{ devId: 'DEV-002', name: '肥猫' }],
    '女频': [{ devId: 'DEV-010', name: '桔子' }],
    '系统': [{ devId: 'DEV-002', name: '肥猫' }, { devId: 'DEV-010', name: '桔子' }],
    '跨频': [{ devId: 'DEV-002', name: '肥猫' }, { devId: 'DEV-010', name: '桔子' }]
  };
  return APPROVER_MAP[channel] || APPROVER_MAP['系统'];
}

module.exports = router;

10.5 文件新增清单Phase 8

backend/api-server/routes/approval.js     ← 授权流程接口
backend/api-server/config/approvers.json  ← 授权人配置(肥猫+桔子)
docs/js/approval-ui.js                    ← 前端授权弹窗 UI
docs/css/approval.css                     ← 授权弹窗样式

十一、补充条款 S3 · 系统自治权与冰朔指令签发模式Phase 9

补充签发霜砚AG-SY-01· 冰朔授权

补充时间2026-03-25 13:50 CST

11.1 双线并行架构

11.2 系统自治权

11.3 执行顺序

11.4 回执要求

[ZY-LANGDRIVE-RECEIPT-8]
Phase: 8 · 双环境部署流 + 天眼终审授权
授权流程接口: ✅/❌
天眼→授权人推送: ✅/❌
授权人点击确认: ✅/❌
自动发布触发: ✅/❌
审计日志: ✅/❌

[ZY-LANGDRIVE-RECEIPT-9]
Phase: 9 · 系统自治运行框架
自动监控: ✅/❌
自动优化: ✅/❌
审计日志: ✅/❌

🔗 签发霜砚AG-SY-01

👤 授权冰朔TCS-0002∞

📅 日期2026-03-25

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