--- belongs_to: - "[[INDEX · 铸渊·协作指令|GitHub ↔ Notion 桥接协议]]" --- # 🗣️ 铸渊指令|语言驱动执行层 · 写入能力 + 意图路由 + 开发者权限沙箱 + 认知引导系统(ZY-LANGDRIVE-2026-0325-001)· 霜砚签发 · 冰朔授权 --- ## 零、为什么需要这个指令 双通道(ZY-DUALCHANNEL)解决的是**「读」**——铸渊能看到 Notion 数据、GitHub 状态。 但语言驱动操作系统需要的不只是读,还需要: | 能力层 | 说明 | 双通道能解决吗? | | --- | --- | --- | | **能读** | 铸渊知道开发者信息、系统状态 | ✅ 双通道已解决 | | **能写** | 开发者说"帮我建个工单"→系统真的建了 | ❌ 还没做 | | **能理解** | 开发者说自然语言→系统知道该调哪个API | ❌ 还没做 | | **能保护** | 开发者说错话不会炸掉系统 | ❌ 还没做 | | **能引导** | 新开发者不会用→系统教会怎么说话 | ❌ 还没做 | **本指令补全后四层。** --- ## 一、总体架构 ```jsx 开发者登录交互页面 │ │ 说一句自然语言 │ 例如:"帮我看看我的工单还有几个没关" ▼ ┌─────────────────────────────────────────────────────────────┐ │ 意图路由引擎(Intent Router) │ │ │ │ 自然语言 → 解析意图 → 匹配操作 → 权限检查 → 执行/拒绝 │ │ │ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │ │ 意图识别 │→│ 操作映射 │→│ 权限检查 │→│ 执行引擎 │ │ │ │ │ │ │ │ │ │ │ │ │ │ NLP解析 │ │ 查工单 │ │ 预览站? │ │ 调API │ │ │ │ 关键词匹配│ │ 建工单 │ │ 正式站? │ │ 返回结果 │ │ │ │ 上下文推断│ │ 查进度 │ │ 只读? │ │ 写回执 │ │ │ │ │ │ 部署模块 │ │ 可写? │ │ │ │ │ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │ │ │ │ ┌──────────────────────────────────────────────────────┐ │ │ │ 安全沙箱层(Sandbox Guard) │ │ │ │ │ │ │ │ 预览站:所有操作在沙箱中执行,不影响真实系统 │ │ │ │ 正式站:操作真实执行,但受权限等级限制 │ │ │ │ 危险操作:二次确认 + 人类审批 │ │ │ └──────────────────────────────────────────────────────┘ │ └─────────────────────────────────────────────────────────────┘ │ ▼ 通道B(后端中间层)调用真实 API ├── Notion API → 建工单、查数据、更新状态 ├── GitHub API → 查PR、触发部署、查代码 └── 系统内部 → 广播、SYSLOG、Agent注册表 ``` --- ## 二、写入能力层(Phase 3 · 通道B扩展) ### 2.1 目标 在通道B后端中间层上扩展**写入API**,让铸渊交互页面不仅能读数据,还能**真的改数据**。 ### 2.2 新增 API 接口 在 `backend/api-server/routes/` 中新增以下写入接口: ```jsx // ====== 写入类接口 ====== // 工单系统 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` ```jsx 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` ```jsx 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` ```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` ```jsx 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 模型知道自己能调用哪些操作: ```jsx // 前端 · 构建带 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 双环境权限模型 ```jsx ┌─────────────────────────────────────────────────────────────┐ │ 权限分层模型 │ │ │ │ Level 0 · 观察者(新开发者默认) │ │ ├── 只读所有数据 │ │ ├── 不能写入任何东西 │ │ ├── 可以和铸渊聊天、问问题 │ │ └── 目的:先熟悉系统,看看别人怎么用 │ │ │ │ Level 1 · 学习者(通过认知引导后升级) │ │ ├── 预览站:可以执行所有操作(沙箱环境,不影响真实系统) │ │ ├── 正式站:只读 │ │ ├── 可以建工单、提SYSLOG、部署到预览站 │ │ └── 目的:在安全环境中学会「怎么说话」 │ │ │ │ Level 2 · 执行者(冰朔手动升级) │ │ ├── 预览站:全部权限 │ │ ├── 正式站:可以执行自己模块范围内的操作 │ │ ├── 可以部署自己负责的模块到正式站 │ │ ├── 不能动其他开发者的模块 │ │ └── 目的:正式参与系统运作 │ │ │ │ Level 3 · 管理者(仅冰朔 + 霜砚) │ │ ├── 全部权限,包括所有模块 │ │ ├── 可以升级/降级其他开发者的权限 │ │ ├── 可以执行系统级操作(广播、Agent管理等) │ │ └── 目的:系统管理 │ └─────────────────────────────────────────────────────────────┘ ``` ### 4.3 权限配置文件 创建文件:`backend/api-server/config/permissions.js` ```jsx // 权限等级定义 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` ```jsx 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` ```jsx 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` ```jsx /** * 沙箱中间件 * * 如果开发者在预览环境中执行写入操作: * - 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 新开发者首次登录流程 ```jsx 新开发者首次登录 │ ▼ ┌─────────────────────────────────────────┐ │ 👋 欢迎来到光湖·数字地球 │ │ │ │ 我是铸渊,你的代码守护人格体。 │ │ 在这里,你不需要点按钮或填表单。 │ │ **直接对我说话就好。** │ │ │ │ 比如你可以说: │ │ · "我的工单还有几个没关?" │ │ · "帮我建一个P2的Bug工单" │ │ · "我想部署 status-board 到预览站" │ │ · "最近系统有什么日志?" │ │ │ │ 现在你在**预览环境**,所有操作都不会 │ │ 影响正式站。放心练习。 │ │ │ │ 准备好了吗?试着和我说句话。 │ │ │ │ [开始体验] → │ └─────────────────────────────────────────┘ │ ▼ 进入引导对话(系统预设 5 轮引导) ``` ### 5.3 引导对话脚本(5轮) 创建文件:`backend/api-server/config/onboarding-script.json` ```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 引导完成后自动升级权限 ```jsx // 引导完成后,自动将开发者从 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 升级路径 ```jsx 观察者(L0) ──完成5轮引导──→ 学习者(L1) ──冰朔手动升级──→ 执行者(L2) │ │ │ 预览站:全部可操作 │ 正式站:可操作自己模块 │ 正式站:只读 │ 含部署权限 │ │ └──── 认知适应期 ────────────────┘ (时间由冰朔决定) ``` **升级到 Level 2 的条件**(由冰朔判断): - 在预览站操作至少 7 天 - 至少完成 10 次有效操作(建工单、提日志、部署预览等) - 没有误操作记录 - 冰朔主观判断:这个人已经知道「怎么说话」了 --- ## 六、文件创建清单 ```jsx 新增文件清单(全部在 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 分别回执: ```jsx [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](http://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` ```jsx 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 >