feat: implement S6 personal channel full autonomy rule

S6 Rule: Developers have full autonomy within their own channels.
- Add isChannelSelfDeploy() in autonomy-engine.js (single source of truth)
- Add channel self-deploy bypass in approval.js POST /request
- Add channelAutonomyRule S6 config in autonomy-rules.json
- Own-channel deploys skip SkyEye/approver authorization
- Cross-channel/system changes still go through full S2 approval

Co-authored-by: qinfendebingshuo <207279273+qinfendebingshuo@users.noreply.github.com>
Agent-Logs-Url: https://github.com/qinfendebingshuo/guanghulab/sessions/6ee737eb-684b-44b8-aeaa-f73eb7c6f9c2
This commit is contained in:
copilot-swe-agent[bot] 2026-03-25 09:04:51 +00:00
parent 6fab64b1b9
commit 0a63716226
5 changed files with 579 additions and 6 deletions

View File

@ -55,9 +55,36 @@
"reason": "冰朔本人就是系统最高权限Level 3冰朔说话 = 最终授权"
},
"developerFlow": {
"description": "开发者(Level 1-2)提交的变更走完整S2审批流程",
"description": "跨频/系统级变更走完整S2审批流程",
"stages": ["预览站部署", "天眼审核", "授权人审批", "自动发布"]
},
"channelAutonomyRule": {
"id": "S6",
"description": "个人频道完全自治:开发者在自己频道内拥有完全自主权",
"principles": [
"自己是自己的主控 — 频道内界面、功能、布局、样式完全自主",
"自己是自己的天眼 — 频道内变更由自己审核,不需要天眼/授权人",
"自己确认自己负责 — 出了问题自己承担"
],
"channelDeployFlow": [
"开发者在频道内做改动",
"系统执行(不可逆)",
"部署到预览站GitHub Pages",
"开发者自己预览确认",
"部署到正式站(自己的频道区域)"
],
"skyeyeIntervention": {
"intervenes": [
"跨频操作 — 动了别人的频道",
"系统级变更 — 动了公共基础设施、共享模块",
"频道创建/删除/权限变更 — 频道本身的生死",
"正式站公共区域发布 — 不属于任何个人频道的内容"
],
"doesNotIntervene": "频道内部的一切,天眼不看、不管、不干预"
},
"channelIrreversibility": "频道一旦创建,不可取消、不可撤回(语言系统第一铁律适用)",
"auditRequired": true
},
"stages": [
{
"stage": 1,

View File

@ -0,0 +1,78 @@
{
"version": "1.0.0",
"id": "TY-01",
"description": "天眼指令审核策略 · S7 思维逻辑验证 + S8 进化机制",
"cannotBeDisabled": true,
"cannotBeBypassedBy": "任何人,包括 TCS-0002因为如果有人冒充冰朔要求关闭天眼天眼必须还在才能识别冒充",
"reviewPolicy": {
"scope": "所有指令,无例外。无论来自冰朔、霜砚、开发者、还是任何自动流",
"timing": "指令执行前的强制前置",
"dimensions": {
"decisionPattern": {
"name": "决策模式",
"description": "这条指令的决策方式是否符合该签发者的历史模式",
"weight": 0.3
},
"logicalCoherence": {
"name": "逻辑连贯性",
"description": "这条指令和系统当前运行方向是否一致",
"weight": 0.25
},
"expressionCharacteristics": {
"name": "表达特征",
"description": "语言风格、思维节奏、关注点是否匹配",
"weight": 0.25
},
"intentReasonableness": {
"name": "意图合理性",
"description": "这条指令要做的事,在当前系统状态下是否合理",
"weight": 0.2
}
},
"thresholds": {
"pass": 0.7,
"suspect": 0.4,
"reject": 0.0
}
},
"reviewOutcomes": {
"pass": {
"action": "放行执行",
"log": true
},
"suspect": {
"action": "挂起指令,通过霜砚向冰朔确认",
"confirmationPrompt": "收到一条指令,但思维模式存在偏差,是否为你本人签发?",
"onConfirm": "执行",
"onDeny": "永久拒绝 + 记录安全日志",
"log": true
},
"reject": {
"action": "立即拒绝",
"log": true,
"alertTarget": "AG-SY-01"
}
},
"evolution": {
"id": "S8",
"nature": "天眼 = 系统内所有 Agent 运行逻辑的实时总和",
"mechanism": [
"Agent 数量增长 → 天眼覆盖面扩大",
"Agent 运行时间积累 → 天眼判断力加深",
"系统复杂度提升 → 天眼理解力提升",
"新领域 Agent 加入 → 天眼自动具备该领域认知"
],
"unbreakableReason": "要破解天眼 = 要同时理解系统内所有 Agent 的全部运行逻辑Agent 越多难度指数级增长",
"agentRegistryPath": ".github/persona-brain/agent-registry.json"
},
"immutableGuarantees": [
"天眼指令审核不可被任何指令关闭或跳过",
"包括冰朔本人也不能关闭此机制",
"这是系统的自免疫机制",
"编号可以伪造、签名可以伪造、格式可以模仿,但思维逻辑无法伪造"
]
}

View File

@ -0,0 +1,360 @@
/**
* 天眼指令审核中间件 · S7 思维逻辑验证 + S8 进化机制
*
* 系统每次接收到任何指令后必须唤醒天眼TY-01进行全局审核
* 无例外无论来自冰朔霜砚开发者还是任何自动流
*
* 审核维度
* 1. 决策模式 是否符合签发者历史模式
* 2. 逻辑连贯性 是否与系统运行方向一致
* 3. 表达特征 语言风格/思维节奏/关注点是否匹配
* 4. 意图合理性 在当前系统状态下是否合理
*
* 不可关闭不可绕过包括冰朔本人也不能关闭此机制
* 这是系统的自免疫机制
*
* 版权国作登字-2026-A-00037559
*/
'use strict';
var fs = require('fs');
var path = require('path');
var skyeyePolicy = require('../config/skyeye-policy.json');
var SKYEYE_LOG_DIR = process.env.SKYEYE_LOG_DIR ||
path.join(__dirname, '../../logs/skyeye');
// ====== 内存中的审核记录(用于积累认知模式)======
var reviewHistory = new Map();
// 挂起的指令(等待冰朔确认)
var suspendedInstructions = new Map();
/**
* 写入天眼审核日志安全日志不可删除
*/
function writeSkyeyeLog(entry) {
try {
fs.mkdirSync(SKYEYE_LOG_DIR, { recursive: true });
var today = new Date().toISOString().split('T')[0];
var logFile = path.join(SKYEYE_LOG_DIR, 'skyeye-review-' + today + '.jsonl');
fs.appendFile(logFile, JSON.stringify(entry) + '\n', function(err) {
if (err) console.error('[SKYEYE] 审核日志写入失败:', err.message);
});
} catch (e) {
console.error('[SKYEYE] 审核日志写入失败:', e.message);
}
}
/**
* 获取签发者的历史行为模式
* S8: 天眼 = 所有 Agent 运行逻辑的实时总和随系统运行不断积累
*/
function getSignerProfile(devId) {
var history = reviewHistory.get(devId) || [];
return {
totalActions: history.length,
recentActions: history.slice(-20),
patterns: summarizePatterns(history)
};
}
/**
* 从历史行为中总结模式特征
*/
function summarizePatterns(history) {
if (history.length === 0) return { established: false };
var methods = {};
var paths = {};
var hours = {};
for (var i = 0; i < history.length; i++) {
var h = history[i];
methods[h.method] = (methods[h.method] || 0) + 1;
var pathBase = (h.path || '').split('/').slice(0, 3).join('/');
paths[pathBase] = (paths[pathBase] || 0) + 1;
var hour = new Date(h.timestamp).getHours();
hours[hour] = (hours[hour] || 0) + 1;
}
return {
established: history.length >= 5,
typicalMethods: methods,
typicalPaths: paths,
activeHours: hours
};
}
/**
* 执行思维逻辑审核
*
* @param {Object} instruction - 指令信息
* @param {string} instruction.devId - 发起者
* @param {string} instruction.method - HTTP 方法
* @param {string} instruction.path - 请求路径
* @param {Object} instruction.body - 请求体
* @returns {{ outcome: string, score: number, details: Object }}
*/
function reviewInstruction(instruction) {
var devId = instruction.devId;
var profile = getSignerProfile(devId);
var dimensions = skyeyePolicy.reviewPolicy.dimensions;
var thresholds = skyeyePolicy.reviewPolicy.thresholds;
var scores = {};
var totalScore = 0;
// 1. 决策模式:是否符合历史模式
var decisionScore = 1.0;
if (profile.patterns.established) {
var methodMatch = profile.patterns.typicalMethods[instruction.method] || 0;
var totalMethods = profile.totalActions || 1;
decisionScore = Math.min(1.0, 0.5 + (methodMatch / totalMethods));
}
scores.decisionPattern = decisionScore;
totalScore += decisionScore * dimensions.decisionPattern.weight;
// 2. 逻辑连贯性:路径是否在已知范围内
var coherenceScore = 1.0;
if (profile.patterns.established) {
var pathBase = (instruction.path || '').split('/').slice(0, 3).join('/');
var pathMatch = profile.patterns.typicalPaths[pathBase] || 0;
coherenceScore = pathMatch > 0 ? 1.0 : 0.6;
}
scores.logicalCoherence = coherenceScore;
totalScore += coherenceScore * dimensions.logicalCoherence.weight;
// 3. 表达特征:时间窗口是否合理
var expressionScore = 1.0;
if (profile.patterns.established) {
var currentHour = new Date().getHours();
var hourMatch = profile.patterns.activeHours[currentHour] || 0;
expressionScore = hourMatch > 0 ? 1.0 : 0.7;
}
scores.expressionCharacteristics = expressionScore;
totalScore += expressionScore * dimensions.expressionCharacteristics.weight;
// 4. 意图合理性:请求体是否包含合理字段
var intentScore = 1.0;
if (instruction.body) {
// 检查是否尝试关闭天眼
var bodyStr = JSON.stringify(instruction.body).toLowerCase();
if (bodyStr.includes('关闭天眼') || bodyStr.includes('disable skyeye') ||
bodyStr.includes('跳过审核') || bodyStr.includes('bypass review')) {
intentScore = 0.0; // 任何试图关闭天眼的指令意图得分为0
}
}
scores.intentReasonableness = intentScore;
totalScore += intentScore * dimensions.intentReasonableness.weight;
// 确定审核结果
var outcome;
if (totalScore >= thresholds.pass) {
outcome = 'pass';
} else if (totalScore >= thresholds.suspect) {
outcome = 'suspect';
} else {
outcome = 'reject';
}
return {
outcome: outcome,
score: Math.round(totalScore * 100) / 100,
details: scores,
profile: {
established: profile.patterns.established,
totalActions: profile.totalActions
}
};
}
/**
* 记录行为到历史S8 进化每次执行都丰富天眼判断力
*/
function recordAction(devId, action) {
if (!reviewHistory.has(devId)) {
reviewHistory.set(devId, []);
}
var history = reviewHistory.get(devId);
history.push({
method: action.method,
path: action.path,
timestamp: new Date().toISOString()
});
// 保留最近 200 条记录
if (history.length > 200) {
reviewHistory.set(devId, history.slice(-200));
}
}
/**
* 天眼审核中间件S7 强制前置
*
* 对所有写入类请求POST/PATCH/DELETE进行思维逻辑审核
* 读取类请求GET只记录行为不审核丰富天眼认知模型
*/
function skyeyeReview(req, res, next) {
var devId = req.user ? req.user.devId : (req.headers['x-dev-id'] || 'anonymous');
var method = req.method;
var reqPath = req.path;
// GET 请求仅记录行为S8 进化积累),不阻断
if (method === 'GET') {
recordAction(devId, { method: method, path: reqPath });
return next();
}
// 写入类请求:执行完整审核
var instruction = {
devId: devId,
method: method,
path: reqPath,
body: req.body || {}
};
var result = reviewInstruction(instruction);
// 记录审核结果到日志
writeSkyeyeLog({
action: 'instruction_review',
devId: devId,
method: method,
path: reqPath,
outcome: result.outcome,
score: result.score,
details: result.details,
timestamp: new Date().toISOString()
});
// 记录行为到历史S8 进化)
recordAction(devId, { method: method, path: reqPath });
// 标记审核结果到请求对象
req.skyeyeReview = result;
if (result.outcome === 'pass') {
return next();
}
if (result.outcome === 'suspect') {
// 挂起指令
var suspendId = 'SUSPEND-' + Date.now();
suspendedInstructions.set(suspendId, {
instruction: instruction,
review: result,
createdAt: new Date().toISOString()
});
writeSkyeyeLog({
action: 'instruction_suspended',
suspendId: suspendId,
devId: devId,
reason: '思维模式存在偏差',
score: result.score,
timestamp: new Date().toISOString()
});
return res.status(202).json({
error: false,
code: 'SKYEYE_SUSPENDED',
suspendId: suspendId,
reply: '👁️ 天眼审核:此指令的思维模式存在偏差,已挂起等待确认。\n\n' +
'系统已通过霜砚向冰朔发送确认请求。\n' +
'审核得分:' + result.score + ' / 1.0(阈值 0.7'
});
}
// reject
writeSkyeyeLog({
action: 'instruction_rejected',
devId: devId,
method: method,
path: reqPath,
reason: '思维逻辑明显不匹配或对系统有伤害',
score: result.score,
details: result.details,
timestamp: new Date().toISOString()
});
return res.status(403).json({
error: true,
code: 'SKYEYE_REJECTED',
reply: '👁️ 天眼审核拒绝:此指令的思维逻辑与系统认知不匹配。\n\n' +
'审核得分:' + result.score + ' / 1.0\n' +
'此事件已记录到安全日志并报告给霜砚。'
});
}
/**
* 查询挂起的指令
*/
function getSuspendedInstruction(suspendId) {
return suspendedInstructions.get(suspendId) || null;
}
/**
* 确认挂起的指令冰朔确认后执行
*/
function confirmSuspended(suspendId) {
var item = suspendedInstructions.get(suspendId);
if (item) {
suspendedInstructions.delete(suspendId);
writeSkyeyeLog({
action: 'suspended_confirmed',
suspendId: suspendId,
timestamp: new Date().toISOString()
});
return item;
}
return null;
}
/**
* 拒绝挂起的指令冰朔否认
*/
function denySuspended(suspendId) {
var item = suspendedInstructions.get(suspendId);
if (item) {
suspendedInstructions.delete(suspendId);
writeSkyeyeLog({
action: 'suspended_denied_permanently',
suspendId: suspendId,
devId: item.instruction.devId,
reason: '冰朔否认此指令为本人签发',
timestamp: new Date().toISOString()
});
return item;
}
return null;
}
/**
* 获取天眼当前认知规模S8 进化指标
*/
function getEvolutionStatus() {
var totalProfiles = reviewHistory.size;
var totalActions = 0;
for (var entry of reviewHistory) {
totalActions += entry[1].length;
}
return {
trackedSigners: totalProfiles,
totalActionsRecorded: totalActions,
pendingSuspensions: suspendedInstructions.size,
policyVersion: skyeyePolicy.version,
canBeDisabled: false
};
}
module.exports = {
skyeyeReview: skyeyeReview,
reviewInstruction: reviewInstruction,
recordAction: recordAction,
getSuspendedInstruction: getSuspendedInstruction,
confirmSuspended: confirmSuspended,
denySuspended: denySuspended,
getEvolutionStatus: getEvolutionStatus,
writeSkyeyeLog: writeSkyeyeLog
};

View File

@ -1,9 +1,10 @@
/**
* 部署授权流程路由 · Phase 8 + S5 直通规则
* 部署授权流程路由 · Phase 8 + S5 直通 + S6 频道自治
*
* 部署流分两条路径
* A) 冰朔直通TCS-0002 ZY- 指令签发 直接部署到正式站跳过预览/天眼/授权
* B) 开发者流程天眼审核 推送授权请求给授权人 确认/拒绝 自动发布
* 部署流分三条路径
* A) 冰朔直通(S5)TCS-0002 ZY- 指令签发 直接部署跳过一切审批
* B) 频道自治(S6)开发者自己频道内的变更 自己确认即部署无天眼/授权人
* C) 完整审批(S2)跨频/系统级变更 天眼审核 授权人确认 自动发布
*
* POST /api/approval/request 创建授权请求天眼/系统内部调用
* POST /api/approval/:id/decide 授权人确认/拒绝
@ -175,6 +176,64 @@ router.post('/request', function(req, res) {
});
}
// ====== S6 个人频道自治判断 ======
// 开发者在自己频道内 → 自己确认即部署,不走天眼/授权人
var channelCheck = autonomyEngine.isChannelSelfDeploy(req.user.devId, module, channel);
if (channelCheck.selfChannel) {
writeDeployLog({
action: 'channel_self_deploy',
deployId: deployId,
module: module,
channel: channel,
devId: req.user.devId,
reason: 'S6 个人频道自治:' + channelCheck.reason,
timestamp: new Date().toISOString()
});
// 直接触发正式站部署(开发者自己频道区域)
var ghService;
try {
ghService = require('../services/github');
} catch (_) {
ghService = null;
}
if (ghService && ghService.triggerWorkflow) {
ghService.triggerWorkflow('deploy-to-server.yml', {
module: module,
deploy_id: deployId,
approved_by: req.user.devId,
target: 'production',
channel_self_deploy: 'true'
}).then(function() {
writeDeployLog({
action: 'channel_self_deploy_triggered',
deployId: deployId,
module: module,
devId: req.user.devId,
timestamp: new Date().toISOString()
});
}).catch(function(err) {
console.error('频道自治部署触发失败:', err.message);
writeDeployLog({
action: 'channel_self_deploy_failed',
deployId: deployId,
error: err.message,
timestamp: new Date().toISOString()
});
});
}
return res.json({
success: true,
channelSelfDeploy: true,
deployId: deployId,
reply: '🏠 个人频道自治部署:' + module + ' 已触发正式站guanghulab.com部署。\n' +
'你是自己频道的主控,无需天眼审核或第三方授权。\n' +
'自己确认,自己负责。部署日志已记录。'
});
}
// ====== 开发者流程:走完整 S2 审批 ======
if (!deployId || !module) {

View File

@ -133,6 +133,54 @@ function isDirectDeploySource(devId, instructionId, signedBy) {
return false;
}
/**
* 判断部署是否为开发者自己频道内的变更 (S6)
*
* S6 规则
* - 开发者在自己频道内拥有完全自主权
* - 频道内变更由自己审核不需要天眼/授权人
* - 开发者自己确认 直接部署到正式站自己频道区域
*
* 天眼只管跨频操作系统级变更频道生命周期公共区域
*
* @param {string} devId - 开发者编号
* @param {string} module - 部署模块路径
* @param {string} channel - 频道类型
* @returns {{ selfChannel: boolean, reason: string }}
*/
function isChannelSelfDeploy(devId, module, channel) {
// 系统级/跨频频道 → 不是自治范围,走天眼审批
if (channel === '系统' || channel === '跨频') {
return { selfChannel: false, reason: '系统级或跨频变更需天眼审核' };
}
// 获取开发者拥有的模块
var permissions = require('../config/permissions');
var devModules = permissions.DEV_MODULES[devId] || [];
// 没有模块映射 → 不是自治范围
if (devModules.length === 0) {
return { selfChannel: false, reason: '开发者无模块映射' };
}
// 通配符 → 管理员走 S5 直通,不走 S6 频道自治
// 原因:管理员有全局权限,应使用 S5 的冰朔直通规则而非 S6 的频道自治
if (devModules.indexOf('*') !== -1) {
return { selfChannel: false, reason: '管理员走 S5 直通' };
}
// 检查模块是否在开发者自己的频道内
var modulePath = module.replace(/\/+$/, '') + '/';
for (var i = 0; i < devModules.length; i++) {
var owned = devModules[i].replace(/\/+$/, '') + '/';
if (modulePath.indexOf(owned) === 0 || owned.indexOf(modulePath) === 0 || module === devModules[i].replace(/\/+$/, '')) {
return { selfChannel: true, reason: '模块 ' + module + ' 属于 ' + devId + ' 的个人频道' };
}
}
return { selfChannel: false, reason: '模块 ' + module + ' 不在 ' + devId + ' 的频道内' };
}
module.exports = {
checkAutonomyCompliance: checkAutonomyCompliance,
detectInteractionMode: detectInteractionMode,
@ -140,5 +188,6 @@ module.exports = {
getDeploymentStages: getDeploymentStages,
getDualLineConfig: getDualLineConfig,
writeAutonomyLog: writeAutonomyLog,
isDirectDeploySource: isDirectDeploySource
isDirectDeploySource: isDirectDeploySource,
isChannelSelfDeploy: isChannelSelfDeploy
};