guanghulab/scripts/neural/track-work-orders.js

225 lines
7.0 KiB
JavaScript
Raw Permalink Normal View History

// scripts/neural/track-work-orders.js
// 🧬 工单追踪器
// 铸渊每次唤醒时运行,追踪所有活跃工单状态
// 检查超时、匹配回执、更新状态、生成追踪报告
//
// 指令回执追踪表配置Notion 侧)
// 数据库位置:光湖语言壳 > 统一网关 > 指令回执追踪表
// 写入脚本scripts/neural/write-receipt-to-notion.js
const fs = require('fs');
const path = require('path');
var WORK_ORDER_DIR = 'data/neural-reports/work-orders';
var COMPLETED_DIR = 'data/deploy-queue/completed';
var RECEIPT_DIR = 'data/neural-reports/receipts';
var TRACKER_DIR = 'data/neural-reports/work-orders';
var TERMINAL_STATUSES = ['CLOSED', 'ESCALATED', 'VERIFIED'];
// ━━━ 指令回执追踪配置 ━━━
var RECEIPT_TRACKER_CONFIG = {
// 指令回执追踪表 · Notion Database ID
// 位于:光湖语言壳 > 统一网关 > 指令回执追踪表
// 实际 Database ID 通过此环境变量名读取(安全考虑不硬编码)
databaseIdEnvVar: 'RECEIPT_DB_ID',
// 字段映射(与 Notion 数据库字段名一一对应)
fieldMap: {
instructionId: '指令编号', // title
summary: '指令摘要', // text
status: '执行状态', // status
receipt: '铸渊回执', // text
receiptTime: '回执时间', // date
newFiles: '新增文件数', // number
modifiedFiles: '修改文件数', // number
relatedAgent: '关联Agent', // text
timeoutStatus: '回执超时', // select
},
// 超时阈值(小时)
timeoutThresholds: {
warning: 24, // 24h → 🟡 接近超时
critical: 72, // 72h → 🔴 已超时
}
};
function loadJSON(p) {
try { return JSON.parse(fs.readFileSync(p, 'utf8')); }
catch (e) { return null; }
}
function getActiveWorkOrders() {
if (!fs.existsSync(WORK_ORDER_DIR)) return [];
var allOrders = [];
var files = fs.readdirSync(WORK_ORDER_DIR)
.filter(function(f) { return f.startsWith('work-orders-') && f.endsWith('.json'); });
for (var i = 0; i < files.length; i++) {
var data = loadJSON(path.join(WORK_ORDER_DIR, files[i]));
if (data && data.work_orders) {
for (var j = 0; j < data.work_orders.length; j++) {
allOrders.push(data.work_orders[j]);
}
}
}
return allOrders.filter(function(wo) {
return TERMINAL_STATUSES.indexOf(wo.status) === -1;
});
}
function getCompletedReceipts() {
var receipts = {};
// 从 deploy-queue/completed 收集
if (fs.existsSync(COMPLETED_DIR)) {
var files = fs.readdirSync(COMPLETED_DIR)
.filter(function(f) { return f.endsWith('.json'); });
for (var i = 0; i < files.length; i++) {
var receipt = loadJSON(path.join(COMPLETED_DIR, files[i]));
if (receipt && receipt.command_id) {
receipts[receipt.command_id] = receipt;
}
}
}
// 从 neural-reports/receipts 收集本地回执
if (fs.existsSync(RECEIPT_DIR)) {
var receiptFiles = fs.readdirSync(RECEIPT_DIR)
.filter(function(f) { return f.endsWith('.json'); });
for (var j = 0; j < receiptFiles.length; j++) {
var localReceipt = loadJSON(path.join(RECEIPT_DIR, receiptFiles[j]));
if (localReceipt && localReceipt.instruction_id) {
receipts[localReceipt.instruction_id] = localReceipt;
}
}
}
return receipts;
}
function checkTimeout(workOrder) {
var timeout = workOrder.timeout_hours || RECEIPT_TRACKER_CONFIG.timeoutThresholds.critical;
var created = new Date(workOrder.created);
var now = new Date();
var elapsed = (now - created) / (1000 * 60 * 60);
return elapsed > timeout;
}
function getTimeoutStatus(workOrder) {
var created = new Date(workOrder.created);
var now = new Date();
var elapsed = (now - created) / (1000 * 60 * 60);
if (elapsed > RECEIPT_TRACKER_CONFIG.timeoutThresholds.critical) return '🔴 已超时';
if (elapsed > RECEIPT_TRACKER_CONFIG.timeoutThresholds.warning) return '🟡 接近超时';
return '🟢 正常';
}
function trackWorkOrders() {
console.log('\n━━━ 🧬 工单追踪器启动 ━━━\n');
var activeOrders = getActiveWorkOrders();
var receipts = getCompletedReceipts();
console.log('活跃工单: ' + activeOrders.length + ' 个');
var stats = {
total_active: activeOrders.length,
by_status: {},
timed_out: 0,
matched_receipts: 0,
escalated: 0
};
for (var i = 0; i < activeOrders.length; i++) {
var wo = activeOrders[i];
var status = wo.status || 'pending';
// 统计状态分布
if (!stats.by_status[status]) stats.by_status[status] = 0;
stats.by_status[status]++;
// 检查超时
if (checkTimeout(wo)) {
stats.timed_out++;
console.log(' ⏰ 超时: ' + wo.id + ' (' + wo.title + ')');
// 检查是否需要升级
var maxRetries = (wo.constraints && wo.constraints.max_retries) || 2;
if (wo.retry_count >= maxRetries) {
wo.status = 'ESCALATED';
stats.escalated++;
console.log(' 🔺 升级到人类: ' + wo.id);
}
}
// 检查回执匹配
if (wo.command_id && receipts[wo.command_id]) {
var receipt = receipts[wo.command_id];
stats.matched_receipts++;
if (receipt.result && receipt.result.status === 'success') {
wo.status = 'VERIFIED';
console.log(' ✅ 已验证: ' + wo.id + ' (回执成功)');
} else if (receipt.result && receipt.result.status === 'failure') {
wo.status = 'pending';
wo.retry_count = (wo.retry_count || 0) + 1;
console.log(' ❌ 失败: ' + wo.id + ' (重试 ' + wo.retry_count + ')');
}
}
}
// 生成追踪报告
var now = new Date();
var cstTime = new Date(now.getTime() + 8 * 60 * 60 * 1000);
var dateStr = cstTime.toISOString().split('T')[0];
var trackerReport = {
tracker_id: 'TRACKER-' + dateStr,
timestamp: now.toISOString(),
receipt_config: {
database_env_var: RECEIPT_TRACKER_CONFIG.databaseIdEnvVar,
timeout_warning_hours: RECEIPT_TRACKER_CONFIG.timeoutThresholds.warning,
timeout_critical_hours: RECEIPT_TRACKER_CONFIG.timeoutThresholds.critical
},
stats: stats,
active_orders: activeOrders.map(function(wo) {
return {
id: wo.id,
severity: wo.severity,
title: wo.title,
status: wo.status,
created: wo.created,
timed_out: checkTimeout(wo),
timeout_status: getTimeoutStatus(wo)
};
})
};
fs.mkdirSync(TRACKER_DIR, { recursive: true });
fs.writeFileSync(
path.join(TRACKER_DIR, 'tracker-' + dateStr + '.json'),
JSON.stringify(trackerReport, null, 2)
);
console.log('\n📊 追踪报告:');
console.log(' 活跃: ' + stats.total_active);
console.log(' 超时: ' + stats.timed_out);
console.log(' 回执匹配: ' + stats.matched_receipts);
console.log(' 升级: ' + stats.escalated);
console.log(' 状态分布: ' + JSON.stringify(stats.by_status));
console.log('\n━━━ 追踪完成 ━━━\n');
return trackerReport;
}
if (require.main === module) {
trackWorkOrders();
}
module.exports = { trackWorkOrders, RECEIPT_TRACKER_CONFIG };