guanghulab/scripts/neural/track-work-orders.js
Guanghu Domestic Migration d1e47f4565
Some checks are pending
自动更新代码和重启 / update-and-restart (push) Waiting to run
CI检查 + 自动部署 / check (push) Waiting to run
CI检查 + 自动部署 / deploy (push) Blocked by required conditions
重启聊天服务 / restart (push) Waiting to run
chore: import sanitized domestic snapshot for REPO-002
Source snapshot: ca48d3ddf926d79aa138306164169baf764bb829
2026-07-17 15:54:41 +08:00

225 lines
7.0 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// 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 };