feat(plan-management): implement alert-remediation-plan system v1.3
Some checks failed
AI automation / Route event (push) Has been cancelled
AI automation / Hand reopened issue to maintainers (push) Has been cancelled
AI automation / Clean source issue state (push) Has been cancelled
AI automation / Reconcile handoffs (push) Has been cancelled
AI automation / Classify issue (push) Has been cancelled
AI automation / Claude Code smoke (push) Has been cancelled
AI automation / Review issue follow-up (push) Has been cancelled
AI automation / Publish issue follow-up (push) Has been cancelled
AI automation / Implement with Claude Code (push) Has been cancelled
AI automation / Publish implement PR (push) Has been cancelled
AI automation / Continue queued issue comments (push) Has been cancelled
AI automation / Codex review loop (push) Has been cancelled
AI automation / Publish Codex fix (push) Has been cancelled
AI automation / Clear Codex dispatch marker (push) Has been cancelled
AI automation / Own PR re-request Codex (push) Has been cancelled
AI automation / External PR re-request Codex (push) Has been cancelled
AI automation / Poll Codex reaction / retry (push) Has been cancelled
Some checks failed
AI automation / Route event (push) Has been cancelled
AI automation / Hand reopened issue to maintainers (push) Has been cancelled
AI automation / Clean source issue state (push) Has been cancelled
AI automation / Reconcile handoffs (push) Has been cancelled
AI automation / Classify issue (push) Has been cancelled
AI automation / Claude Code smoke (push) Has been cancelled
AI automation / Review issue follow-up (push) Has been cancelled
AI automation / Publish issue follow-up (push) Has been cancelled
AI automation / Implement with Claude Code (push) Has been cancelled
AI automation / Publish implement PR (push) Has been cancelled
AI automation / Continue queued issue comments (push) Has been cancelled
AI automation / Codex review loop (push) Has been cancelled
AI automation / Publish Codex fix (push) Has been cancelled
AI automation / Clear Codex dispatch marker (push) Has been cancelled
AI automation / Own PR re-request Codex (push) Has been cancelled
AI automation / External PR re-request Codex (push) Has been cancelled
AI automation / Poll Codex reaction / retry (push) Has been cancelled
- 8 new store modules + matcher + initialResponse + aggregation + remediation + AlertStateMonitor + planGenerator - alert chain auto-integrated after runInspection: freeze snapshot + generate response + real-time agg + auto-start monitor - AlertAIPanel component + MonitoringDetailPanel expandable alert list - PlanManagementPage: full page with list/edit/AI generate/templates/commands
This commit is contained in:
171
electron/bridges/inspection/planTemplateStore.cjs
Normal file
171
electron/bridges/inspection/planTemplateStore.cjs
Normal file
@@ -0,0 +1,171 @@
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
* 预案模板 CRUD(方案 D7:模板不含匹配条件/双轨步骤,只含公共联动配置)
|
||||
*
|
||||
* 模板结构详见设计方案 §4.2
|
||||
*/
|
||||
|
||||
const { STORAGE_KEY_PLAN_TEMPLATES } = require("./storageKeys.cjs");
|
||||
const { ALERT_LEVELS } = require("./types.cjs");
|
||||
|
||||
let _templates = null;
|
||||
|
||||
function _ensureLoaded(readFn) {
|
||||
if (_templates === null) {
|
||||
const raw = readFn(STORAGE_KEY_PLAN_TEMPLATES);
|
||||
_templates = raw ? _safeParse(raw, []) : _getDefaultTemplates();
|
||||
}
|
||||
}
|
||||
|
||||
function _safeParse(text, def) {
|
||||
if (text === null || text === undefined) return def;
|
||||
if (typeof text === "object") return text;
|
||||
try { return JSON.parse(text); }
|
||||
catch { return def; }
|
||||
}
|
||||
|
||||
function _save(writeFn) {
|
||||
writeFn(STORAGE_KEY_PLAN_TEMPLATES, JSON.stringify(_templates));
|
||||
}
|
||||
|
||||
function _getDefaultTemplates() {
|
||||
const now = Date.now();
|
||||
return [
|
||||
{
|
||||
id: "tpl_level3_critical",
|
||||
name: "三级预案模板(严重)",
|
||||
level: ALERT_LEVELS.CRITICAL,
|
||||
builtin: true,
|
||||
description: "严重级别告警的公共配置:大屏红色闪烁 + 10 分钟自动升级 + 处置需确认",
|
||||
display: { color: "#ef4444", icon: "alert-octagon", blink: true, sound: "builtin_alarm" },
|
||||
notification: {
|
||||
channels: ["desktop", "webhook"],
|
||||
recipients: [{ type: "webhook", target: "" }],
|
||||
repeat_interval_minutes: 5,
|
||||
max_repeats: 12,
|
||||
},
|
||||
escalation_fallback: {
|
||||
auto_escalate_minutes: 30,
|
||||
escalation_target_level: ALERT_LEVELS.CRITICAL,
|
||||
},
|
||||
remediation_defaults: {
|
||||
require_confirmation: true,
|
||||
auto_close_after_remediation_recovery: true,
|
||||
execution_timeout_sec: 120,
|
||||
},
|
||||
created_at: now,
|
||||
updated_at: now,
|
||||
},
|
||||
{
|
||||
id: "tpl_level2_warning",
|
||||
name: "二级预案模板(警告)",
|
||||
level: ALERT_LEVELS.WARNING,
|
||||
builtin: true,
|
||||
description: "警告级别告警的公共配置:大屏橙色提示 + 60 分钟自动升级",
|
||||
display: { color: "#f97316", icon: "alert-triangle", blink: false, sound: null },
|
||||
notification: {
|
||||
channels: ["desktop"],
|
||||
recipients: [],
|
||||
repeat_interval_minutes: 10,
|
||||
max_repeats: 6,
|
||||
},
|
||||
escalation_fallback: {
|
||||
auto_escalate_minutes: 60,
|
||||
escalation_target_level: ALERT_LEVELS.WARNING,
|
||||
},
|
||||
remediation_defaults: {
|
||||
require_confirmation: false,
|
||||
auto_close_after_remediation_recovery: true,
|
||||
execution_timeout_sec: 120,
|
||||
},
|
||||
created_at: now,
|
||||
updated_at: now,
|
||||
},
|
||||
{
|
||||
id: "tpl_level1_info",
|
||||
name: "一级预案模板(提示)",
|
||||
level: ALERT_LEVELS.INFO,
|
||||
builtin: true,
|
||||
description: "提示级别告警的公共配置:大屏蓝色静态展示",
|
||||
display: { color: "#3b82f6", icon: "info", blink: false, sound: null },
|
||||
notification: {
|
||||
channels: ["desktop"],
|
||||
recipients: [],
|
||||
repeat_interval_minutes: 0,
|
||||
max_repeats: 1,
|
||||
},
|
||||
escalation_fallback: null,
|
||||
remediation_defaults: {
|
||||
require_confirmation: false,
|
||||
auto_close_after_remediation_recovery: true,
|
||||
execution_timeout_sec: 120,
|
||||
},
|
||||
created_at: now,
|
||||
updated_at: now,
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
// ---------- CRUD ----------
|
||||
|
||||
function listTemplates(readFn) {
|
||||
_ensureLoaded(readFn);
|
||||
return [..._templates];
|
||||
}
|
||||
|
||||
function getTemplate(readFn, templateId) {
|
||||
_ensureLoaded(readFn);
|
||||
return _templates.find((t) => t.id === templateId) || null;
|
||||
}
|
||||
|
||||
function createTemplate(readFn, writeFn, data) {
|
||||
_ensureLoaded(readFn);
|
||||
const tpl = {
|
||||
id: data.id || `tpl_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`,
|
||||
name: data.name,
|
||||
level: data.level || ALERT_LEVELS.WARNING,
|
||||
builtin: false,
|
||||
description: data.description || "",
|
||||
display: data.display || { color: "#f97316", icon: "alert-triangle", blink: false, sound: null },
|
||||
notification: data.notification || { channels: ["desktop"], recipients: [], repeat_interval_minutes: 10, max_repeats: 6 },
|
||||
escalation_fallback: data.escalation_fallback || null,
|
||||
remediation_defaults: data.remediation_defaults || { require_confirmation: true, auto_close_after_remediation_recovery: true, execution_timeout_sec: 120 },
|
||||
created_at: Date.now(),
|
||||
updated_at: Date.now(),
|
||||
};
|
||||
_templates.push(tpl);
|
||||
_save(writeFn);
|
||||
return { ...tpl };
|
||||
}
|
||||
|
||||
function updateTemplate(readFn, writeFn, templateId, updates) {
|
||||
_ensureLoaded(readFn);
|
||||
const idx = _templates.findIndex((t) => t.id === templateId);
|
||||
if (idx === -1) return null;
|
||||
if (_templates[idx].builtin) return null; // 内置模板不可改
|
||||
_templates[idx] = { ..._templates[idx], ...updates, updated_at: Date.now() };
|
||||
_save(writeFn);
|
||||
return { ..._templates[idx] };
|
||||
}
|
||||
|
||||
function deleteTemplate(readFn, writeFn, templateId) {
|
||||
_ensureLoaded(readFn);
|
||||
const idx = _templates.findIndex((t) => t.id === templateId);
|
||||
if (idx === -1) return false;
|
||||
if (_templates[idx].builtin) return false; // 内置模板不可删
|
||||
_templates.splice(idx, 1);
|
||||
_save(writeFn);
|
||||
return true;
|
||||
}
|
||||
|
||||
function _resetForTest() { _templates = null; }
|
||||
|
||||
module.exports = {
|
||||
listTemplates,
|
||||
getTemplate,
|
||||
createTemplate,
|
||||
updateTemplate,
|
||||
deleteTemplate,
|
||||
_resetForTest,
|
||||
};
|
||||
Reference in New Issue
Block a user