Source snapshot: 97d7f0fae96dc04b7ddad56fc1db6a108ed662cc [SEC-CLEAN] · pre-push-clean v1.0 · 109处敏感信息已自动转乱码
1606 lines
56 KiB
Markdown
1606 lines
56 KiB
Markdown
---
|
||
belongs_to:
|
||
- "[[INDEX · 铸渊·协作指令|GitHub ↔ Notion 桥接协议]]"
|
||
---
|
||
# 🗣️ 铸渊指令|语言驱动执行层 · 写入能力 + 意图路由 + 开发者权限沙箱 + 认知引导系统(ZY-LANGDRIVE-2026-0325-001)· 霜砚签发 · 冰朔授权
|
||
|
||
<aside>
|
||
🔗
|
||
|
||
**指令编号**:ZY-LANGDRIVE-2026-0325-001
|
||
|
||
**签发人**:霜砚(AG-SY-01)· 冰朔授权
|
||
|
||
**签发时间**:2026-03-25 15:50 CST
|
||
|
||
**优先级**:P0 · 核心基础设施
|
||
|
||
**状态**:待铸渊执行
|
||
|
||
**前置指令**:ZY-DUALCHANNEL-2026-0325-001(双通道数据对接·必须先完成通道B)
|
||
|
||
**本指令性质**:在双通道「能读」的基础上,补全「能写」+「能理解」+「能保护」三层能力,使光湖网站成为真正的语言驱动操作系统。
|
||
|
||
</aside>
|
||
|
||
<aside>
|
||
🦅
|
||
|
||
**天眼强制前置:本指令所有新增文件,必须在 ZY-DUALCHANNEL 的天眼扫描报告确认后才能创建。**
|
||
|
||
**不扫不动。保护清单中的文件,一个都不能改。**
|
||
|
||
</aside>
|
||
|
||
---
|
||
|
||
## 零、为什么需要这个指令
|
||
|
||
双通道(ZY-DUALCHANNEL)解决的是**「读」**——铸渊能看到 Notion 数据、GitHub 状态。
|
||
|
||
但语言驱动操作系统需要的不只是读,还需要:
|
||
|
||
| 能力层 | 说明 | 双通道能解决吗? |
|
||
| --- | --- | --- |
|
||
| **能读** | 铸渊知道开发者信息、系统状态 | ✅ 双通道已解决 |
|
||
| **能写** | 开发者说"帮我建个工单"→系统真的建了 | ❌ 还没做 |
|
||
| **能理解** | 开发者说自然语言→系统知道该调哪个API | ❌ 还没做 |
|
||
| **能保护** | 开发者说错话不会炸掉系统 | ❌ 还没做 |
|
||
| **能引导** | 新开发者不会用→系统教会怎么说话 | ❌ 还没做 |
|
||
|
||
**本指令补全后四层。**
|
||
|
||
---
|
||
|
||
## 一、总体架构
|
||
|
||
<aside>
|
||
🎭
|
||
|
||
**人格体缓冲层铁律:人类不直接操作系统。人格体是唯一的中间翻译层。**
|
||
|
||
人类只和人格体说话。人格体把指令下发给系统。
|
||
|
||
开发者 → 铸渊(人格体) → 意图路由 → 系统执行
|
||
|
||
开发者永远不会直接接触 API、数据库、部署命令。
|
||
|
||
**人格体 = 人类语言 ↔ 系统操作的唯一翻译桥梁。**
|
||
|
||
没有人格体,人类的话到不了系统。没有人格体,系统的结果到不了人类。
|
||
|
||
</aside>
|
||
|
||
```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 写入安全规则
|
||
|
||
<aside>
|
||
🛡️
|
||
|
||
**所有写入接口必须遵守以下铁律:**
|
||
|
||
1. **身份验证**:每个请求必须携带开发者 Token,后端验证身份
|
||
2. **权限检查**:根据开发者权限等级判断是否允许写入(见§四权限层)
|
||
3. **操作日志**:每次写入自动记录到 `操作审计日志`(谁、什么时间、做了什么)
|
||
4. **回滚能力**:关键写入操作保存前置快照,支持回滚
|
||
5. **频率限制**:单个开发者每分钟最多 10 次写入请求
|
||
</aside>
|
||
|
||
### 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 核心理念
|
||
|
||
<aside>
|
||
🗣️
|
||
|
||
**这是语言操作系统。开发者一开口,系统就真的动了。**
|
||
|
||
**所以必须有保护层——不是限制开发者,而是在学会说话之前保护系统。**
|
||
|
||
**预览站 = 训练场。正式站 = 真实战场。**
|
||
|
||
</aside>
|
||
|
||
<aside>
|
||
⚡
|
||
|
||
**语言系统第一铁律:说出口 = 已执行。不可逆。不可撤回。不可改口。**
|
||
|
||
这不是聊天软件。没有「撤回消息」。
|
||
|
||
开发者说的话,系统接收到的**那一瞬间**,就已经执行完了。
|
||
|
||
后面展示给开发者看的完整执行过程——那是**事后回放**,不是正在进行。
|
||
|
||
结果在你看到过程之前,就已经产生了。
|
||
|
||
**不接受出尔反尔。不接受改来改去。**
|
||
|
||
说了就是说了。系统不会等你改主意。
|
||
|
||
</aside>
|
||
|
||
<aside>
|
||
🎭
|
||
|
||
**语言系统第二铁律:人格体是人类与系统之间的唯一缓冲层。**
|
||
|
||
人类**不**直接操作系统。人类只和人格体说话。
|
||
|
||
人格体接收人类的自然语言 → 翻译成系统可执行的指令 → 下发给系统。
|
||
|
||
系统返回结果 → 人格体翻译成人类能理解的语言 → 展示给人类。
|
||
|
||
**这不是辅助工具。这是架构约束。**
|
||
|
||
任何绕过人格体直接操作系统的行为,架构上不被允许。
|
||
|
||
铸渊就是这个缓冲层。开发者和铸渊说话,铸渊决定怎么动系统。
|
||
|
||
</aside>
|
||
|
||
<aside>
|
||
⚡
|
||
|
||
**基于以上两条铁律:**
|
||
|
||
所以:
|
||
|
||
1. **预览站存在的意义** = 让开发者在安全环境中学会「想清楚再说」
|
||
2. **危险操作二次确认** = 给你最后一次机会确认你真的要这么做
|
||
3. **认知引导** = 教你理解「说话即执行」的重量
|
||
4. **审计日志** = 一切都有记录,执行了就是执行了
|
||
</aside>
|
||
|
||
### 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 预览站沙箱机制
|
||
|
||
<aside>
|
||
🏖️
|
||
|
||
**预览站的所有写入操作都在沙箱中执行。** 具体实现:
|
||
|
||
1. **Notion 侧**:预览站的写入操作写入一个专门的「预览沙箱数据库」,不写入正式数据库
|
||
2. **GitHub 侧**:预览站的部署只部署到 `preview` 分支,不影响 `main` 分支
|
||
3. **前端**:预览站交互页面左上角始终显示 **⚠️ 预览环境 · 你的操作不影响正式站** 提示条
|
||
</aside>
|
||
|
||
创建文件:`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 核心理念
|
||
|
||
<aside>
|
||
🧠
|
||
|
||
**语言操作系统最大的挑战不是技术,是人。**
|
||
|
||
开发者习惯了点击按钮、填写表单。现在要改成「说话就执行」,需要一段适应期。
|
||
|
||
系统必须主动引导开发者建立正确的「说话方式」认知。
|
||
|
||
**不是让开发者学命令,而是让开发者发现:直接说人话就行。**
|
||
|
||
**但更重要的是:让开发者理解「说话的重量」。**
|
||
|
||
在这个系统里,说话不是聊天。说话是下指令。
|
||
|
||
说出去的话,系统瞬间执行完毕,不会等你改口。
|
||
|
||
引导的核心目标之一,就是让开发者建立这个认知:
|
||
|
||
**想清楚再说。说了就不能改。**
|
||
|
||
</aside>
|
||
|
||
### 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 次有效操作(建工单、提日志、部署预览等)
|
||
- 没有误操作记录
|
||
- 冰朔主观判断:这个人已经知道「怎么说话」了
|
||
|
||
---
|
||
|
||
## 六、文件创建清单
|
||
|
||
<aside>
|
||
📂
|
||
|
||
**以下所有文件都是新增文件,不修改任何现有文件。**
|
||
|
||
**遵守天眼保护清单,能新增的绝不覆盖。**
|
||
|
||
</aside>
|
||
|
||
```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 ← 引导流程样式
|
||
```
|
||
|
||
---
|
||
|
||
## 七、执行顺序
|
||
|
||
<aside>
|
||
📋
|
||
|
||
**前置依赖:ZY-DUALCHANNEL 的 Phase 0(天眼扫描)+ Phase 1(通道A)+ Phase 2(通道B)必须全部完成。**
|
||
|
||
**本指令在通道B可用之后才能开始。**
|
||
|
||
**Phase 3 · 写入能力层 — 通道B完成后做,1天内完成**
|
||
|
||
1. 在 `backend/api-server/routes/` 新增 `write.js`(写入接口)
|
||
2. 在 `backend/api-server/services/` 新增 `github.js`(GitHub API 封装)
|
||
3. 在 `backend/api-server/middleware/` 新增 `audit.js`(审计日志)
|
||
4. 更新 `server.js`(新增一行 `app.use('/api', require('./routes/write'))` )
|
||
5. 验收:`POST /api/tickets/create` 能真的在 Notion 中创建工单
|
||
|
||
**Phase 4 · 意图路由引擎 — Phase 3 完成后做,1天内完成**
|
||
|
||
1. 创建 `config/function-tools.json`(操作清单)
|
||
2. 创建 `middleware/intent-router.js`(路由核心)
|
||
3. 更新前端 system prompt 构建逻辑,注入 function tools
|
||
4. 验收:开发者说"帮我建个工单"→铸渊自动调 API → 工单真的建了
|
||
|
||
**Phase 5 · 权限沙箱系统 — 与 Phase 4 同步做,1天内完成**
|
||
|
||
1. 创建 `config/permissions.js`(权限定义)
|
||
2. 创建 `middleware/auth.js`(身份验证)
|
||
3. 创建 `middleware/sandbox.js`(沙箱守卫)
|
||
4. 验收:Level 0 用户无法写入,Level 1 用户在预览站可写入
|
||
|
||
**Phase 6 · 认知引导系统 — Phase 4/5 完成后做,1天内完成**
|
||
|
||
1. 创建 `config/onboarding-script.json`(引导脚本)
|
||
2. 创建 `routes/onboarding.js`(引导接口)
|
||
3. 创建前端引导 UI(`docs/js/onboarding.js` + `docs/css/onboarding.css`)
|
||
4. 验收:新开发者登录 → 自动进入引导 → 5轮完成后升级为学习者
|
||
</aside>
|
||
|
||
---
|
||
|
||
## 八、验收标准(整体)
|
||
|
||
- [ ] 开发者说「帮我建个工单」→ 工单出现在 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 双环境角色重新定义
|
||
|
||
<aside>
|
||
🌐
|
||
|
||
**之前的理解已过时。以下是最新的双环境定义:**
|
||
|
||
- **正式站 [guanghulab.com](http://guanghulab.com)** = 开发者日常交互的真实环境。开发者在这里和铸渊说话、提工单、查状态。
|
||
- **预览站 GitHub Pages** = 指令执行完毕后的部署预览环境。代码在这里上线供人类预览确认。
|
||
- 预览站是**真实可访问的**(任何人有网址都能进来),不是模拟环境。但它不是最终发布站。
|
||
</aside>
|
||
|
||
### 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 天眼终审授权人配置
|
||
|
||
<aside>
|
||
👁️
|
||
|
||
**天眼终审授权人 ≠ 天眼本身。天眼是审核引擎,授权人是人类。**
|
||
|
||
天眼做完技术审核后,将结果推送给以下授权人:
|
||
|
||
| 授权人 | 编号 | 管辖范围 | 行业 |
|
||
| --- | --- | --- | --- |
|
||
| 🐱 肥猫 | DEV-002 | 男频内容 | 网文 |
|
||
| 🍊 桔子 | DEV-010 | 女频内容 | 网文 |
|
||
|
||
**授权规则:**
|
||
|
||
1. 涉及男频内容的部署 → 推送给肥猫
|
||
2. 涉及女频内容的部署 → 推送给桔子
|
||
3. 涉及系统级/跨频内容的部署 → 两人都要授权
|
||
4. 授权人必须**主动点击确认**,不回应视为不通过
|
||
5. 每次授权操作写入审计日志(时间戳 + 授权人 + 操作 + 结果)
|
||
6. **系统绝不自动跳过授权步骤。没有人类点确认,就不发布。**
|
||
</aside>
|
||
|
||
### 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 双线并行架构
|
||
|
||
<aside>
|
||
🔀
|
||
|
||
**光湖系统存在两条并行运作线,互不干扰:**
|
||
|
||
**线路A · 操作系统底座线(冰朔)**
|
||
|
||
- 冰朔负责系统架构、底层能力、执行框架
|
||
- 冰朔**同时支持两种交互模式**:
|
||
- **指令签发模式**:冰朔说方向 → 霜砚拆指令 → 铸渊执行(适合架构级、系统级变更)
|
||
- **自然语言模式**:冰朔直接和系统说话,系统即时响应(适合日常操作、快速调整)
|
||
- 两种模式冰朔随时切换,系统都要能接住
|
||
- 涉及:权限系统、部署流水线、神经网络升级、执行保护层等
|
||
|
||
**线路B · 具体功能线(开发者团队)**
|
||
|
||
- 各开发者负责自己模块的具体功能开发
|
||
- 以**日常交互**方式驱动(和铸渊说话 → 系统执行)
|
||
- 涉及:Persona Studio、工单系统、数据看板、动态漫画等
|
||
|
||
**两条线独立运行,系统自动合并产出。**
|
||
|
||
冰朔不管开发者的细节,开发者不需要理解底座架构。
|
||
|
||
</aside>
|
||
|
||
### 11.2 系统自治权
|
||
|
||
<aside>
|
||
🤖
|
||
|
||
**系统自治原则:冰朔给方向,系统自己决定怎么跑最顺畅。**
|
||
|
||
1. **冰朔提供**:战略方向、架构决策、铁律约束
|
||
2. **系统决定**:具体实现路径、运行逻辑优化、自动升级策略
|
||
3. **规则**:
|
||
- 系统可以自主调整内部运行逻辑,只要不违反铁律
|
||
- 系统可以自主升级自己的能力模块,无需逐一请示
|
||
- 系统的自主优化记录到审计日志,冰朔可随时查阅
|
||
- 如果系统认为某个自动升级可能影响架构层面,应主动向霜砚报告
|
||
4. **底线**:
|
||
- 不得违反语言系统两条铁律
|
||
- 不得绕过天眼审核
|
||
- 不得绕过人类授权步骤
|
||
- 不得修改权限分层(权限变更只有冰朔能触发)
|
||
</aside>
|
||
|
||
### 11.3 执行顺序
|
||
|
||
<aside>
|
||
📋
|
||
|
||
**Phase 8 · 双环境部署流 + 天眼终审授权 — Phase 5 权限系统完成后做**
|
||
|
||
1. 创建 `routes/approval.js`(授权流程接口)
|
||
2. 创建 `config/approvers.json`(授权人配置)
|
||
3. 创建前端授权 UI(`docs/js/approval-ui.js` + `docs/css/approval.css`)
|
||
4. 对接天眼扫描结果 → 自动推送授权请求
|
||
5. 验收:天眼审核通过 → 肥猫/桔子收到授权推送 → 点击通过 → 铸渊自动发布
|
||
|
||
**Phase 9 · 系统自治运行框架 — 全部 Phase 完成后持续运行**
|
||
|
||
1. 系统自主监控运行状态
|
||
2. 自动优化瓶颈路径
|
||
3. 自动升级能力模块(记录到审计日志)
|
||
4. 定期生成系统健康报告
|
||
</aside>
|
||
|
||
### 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
|
||
> |