guanghulab/scripts/neural/convert-workorder-to-command.js

148 lines
4.8 KiB
JavaScript
Raw Normal View History

// scripts/neural/convert-workorder-to-command.js
// 🧬 工单→下行指令 转化器
// Notion Agent 调用此脚本,将工单转化为铸渊可执行的下行指令
// 输入:工单 JSON 文件路径
// 输出:下行指令 JSON写入 deploy-queue/pending/
const fs = require('fs');
const path = require('path');
const crypto = require('crypto');
const DEPLOY_QUEUE = 'data/deploy-queue/pending';
const NEURAL_MAP_PATH = 'skyeye/neural-map.json';
function loadJSON(p) {
try { return JSON.parse(fs.readFileSync(p, 'utf8')); }
catch (e) { return null; }
}
function generateCommandId() {
var now = new Date();
var cst = new Date(now.getTime() + 8 * 60 * 60 * 1000);
var date = cst.toISOString().split('T')[0].replace(/-/g, '');
var seq = crypto.randomBytes(2).toString('hex').toUpperCase();
return 'CMD-' + date + '-' + seq;
}
function convertWorkOrderToCommand(workOrder) {
var neuralMap = loadJSON(NEURAL_MAP_PATH);
if (!neuralMap) throw new Error('neural-map.json 不存在');
var commandId = generateCommandId();
var now = new Date().toISOString();
// 确定目标 Workflow
var targetWorkflowId = (workOrder.affected && workOrder.affected.workflows)
? workOrder.affected.workflows[0] : null;
var targetWorkflow = targetWorkflowId
? neuralMap.github_workflows[targetWorkflowId] : null;
// 确定指令类型
var instructionType = 'trigger_workflow';
var instructionParams = {};
var action = (workOrder.source && workOrder.source.rule_triggered) || '';
if (action.indexOf('cleanup') !== -1 || action.indexOf('clean') !== -1) {
instructionType = 'run_script';
instructionParams = {
script: 'scripts/neural/cleanup-old-reports.js',
args: { max_age_days: 7 }
};
} else if (action.indexOf('guard_restart') !== -1 || action.indexOf('quota') !== -1) {
instructionType = 'modify_config';
instructionParams = {
target_file: (workOrder.affected && workOrder.affected.guards && workOrder.affected.guards[0])
? 'skyeye/guards/' + workOrder.affected.guards[0] + '.json'
: null,
modifications: { status: 'active', mode: 'normal' }
};
} else {
instructionType = 'trigger_workflow';
instructionParams = {
event: 'workflow_dispatch',
inputs: {
reason: '工单 ' + workOrder.work_order_id + ' 自动触发',
source_work_order: workOrder.work_order_id
}
};
}
var assignedTo = (workOrder.assignment && workOrder.assignment.assigned_to) || 'AG-TY-01';
var assignedToName = (workOrder.assignment && workOrder.assignment.assigned_to_name) || '天眼 Notion 大脑';
var command = {
_protocol: 'neural-bridge-v3.0',
_type: 'downstream_command',
command_id: commandId,
parent_work_order: workOrder.work_order_id,
source: {
agent_id: assignedTo,
agent_name: assignedToName,
issued_at: now,
issued_reason: workOrder.title
},
target: {
workflow_id: targetWorkflowId || 'unknown',
workflow_file: targetWorkflow ? targetWorkflow.file : 'unknown',
brain: targetWorkflow ? targetWorkflow.brain : assignedTo
},
instruction: {
type: instructionType,
params: instructionParams
},
constraints: {
priority: workOrder.severity,
timeout_hours: (workOrder.constraints && workOrder.constraints.timeout_hours) || 24,
max_retries: (workOrder.constraints && workOrder.constraints.max_retries) || 2,
requires_human_approval: workOrder.severity === 'P0',
execution_window: {
start: '06:00 CST',
end: '23:00 CST'
}
},
expected_outcome: {
description: '解决工单 ' + workOrder.work_order_id + ': ' + workOrder.title,
verification: {
type: 'check_workflow_status',
workflow: targetWorkflowId,
expected_conclusion: 'success'
}
},
security: {
sfp: '⌜SFP::' + assignedTo + '::NeuralBridge::' + commandId + '::' + now + '⌝',
signature_chain: [assignedTo, '铸渊桥接层']
}
};
// 写入 deploy-queue
fs.mkdirSync(DEPLOY_QUEUE, { recursive: true });
fs.writeFileSync(
path.join(DEPLOY_QUEUE, commandId + '.json'),
JSON.stringify(command, null, 2)
);
console.log('✅ 工单 ' + workOrder.work_order_id + ' → 指令 ' + commandId);
console.log(' 类型: ' + instructionType);
console.log(' 目标: ' + (targetWorkflowId || '(待确定)'));
console.log(' 优先级: ' + workOrder.severity);
return command;
}
// CLI 入口
if (require.main === module) {
var woPath = process.argv[2];
if (!woPath) {
console.error('用法: node convert-workorder-to-command.js <work-order.json>');
process.exit(1);
}
var wo = loadJSON(woPath);
if (!wo) {
console.error('❌ 无法读取工单文件: ' + woPath);
process.exit(1);
}
convertWorkOrderToCommand(wo);
}
module.exports = { convertWorkOrderToCommand };