规则引擎 ↔ SCSAI 同步架构与运维手册
最后更新:2026-07-23
适用代码:server/core/SCSAI-rule-sync.js、server/core/rule-engine.js、server/core/capability-runtime.js、server/scripts/sync-rules-bidirectional.js、server.js(漂移自检)
1. 权威源与数据流
- 权威存储:SCSAI 的
BossAgent_Rule(2000+ 条,前缀bossagent_*字段)。 - 本地副本:
server/data/rule_engine.db的sciot_rules_v2表(运行时引擎实际读取的库)。 - 方向:
SCSAI → 本地:只读拉取(pull),用item_number(= 本地rule.id)做幂等 upsert。本地 → SCSAI:回写(push),经SCSAIRuleSync.syncRuleToSCSAI,写BossAgent_Rule(不再是废弃的BOS_RULE:Method)。
⚠️ 历史坑(已修复,记录以防回潮)
- 旧版
SCSAIRuleSync把规则写进BOS_RULE:Method(无人读取的死路径)。现已重写为写BossAgent_Rule。 - 旧版建引擎时未传
SCSAIClient→saveRule的回写被整体跳过。现capability-runtime.js建UnifiedRuleEngine时传入this.SCSAIClient。
2. 字段映射(SCSAI BossAgent_Rule ↔ 本地 sciot_rules_v2)
| 本地列 | SCSAI 属性 | 说明 |
|---|---|---|
| id | item_number | upsert key,两端一致 |
| name | name | |
| description | description | |
| scope | bossagent_scope | validate/repair/optimize/compare/generate/identify |
| item_type_name | bossagent_item_type | 适用对象类,* 表示通用 |
| severity | bossagent_severity | info/warn/error |
| priority | bossagent_priority | 整数 |
| condition_script | bossagent_condition_script | TEXT,可空 |
| action_type | bossagent_action_type | suggest/auto_fix/... |
| action_config | bossagent_action_config | JSON 字符串 |
| action_script | bossagent_generated_aml | TEXT,可空 |
| is_active | bossagent_is_active | 0/1 |
| is_builtin | bossagent_is_builtin | 0/1 |
| source | bossagent_source | generated/builtin/inspect/biz/manual/SCSAI |
| version | bossagent_version | 整数 |
| tags | bossagent_tags | CSV 或 JSON 字符串 |
| category | bossagent_category | |
| SCSAI_id | id (@_id) | SCSAI item 的 GUID,回写凭证 |
关键归一化:_SCSAIVal()
SCSAI sendAML 返回的空属性不是 null,而是对象 {is_null:"1"};引用属性可能是 {keyed_name:...}。直接在代码里 value || null 兜底不生效(对象 truthy),会把 object 传进 better-sqlite3 → 绑定失败报 Too few parameter values → 整批跳过(这是此前 PULL 长期 0 条的真凶)。
_SCSAIVal(v) 负责归一化:
- 原始
null/undefined→null - 字符串/数字/布尔 → 字符串
- 对象:含
is_null→null;含#text/keyed_name/value→ 取之;其它 →JSON.stringify落 TEXT 列
3. 同步脚本
server/scripts/sync-rules-bidirectional.js:
node server/scripts/sync-rules-bidirectional.js # 默认:pull(SCSAI → 本地)
node server/scripts/sync-rules-bidirectional.js --push # 本地 → SCSAI(仅 is_builtin=0)
node server/scripts/sync-rules-bidirectional.js --both # 先 pull 再 push
node server/scripts/sync-rules-bidirectional.js --dry # 只读漂移检查,不写任一端
- PULL:
SCSAIRuleSync.syncRulesFromSCSAI(SCSAIClient, engine),按item_numberupsert。maxRecords5000。 - PUSH:遍历本地
is_builtin = 0行,逐条syncRuleToSCSAI。id为 NULL 的行会被跳过(无合法 id 无法映射,非 bug)。 - 漂移自检:
server.js启动后约 15s 报告本地与 SCSAI 的item_number差异(只读 Warn,不写任一端)。
4. 规则生命周期(CRUD 是否回写)
| 操作位置 | 是否回写 SCSAI | 现状 |
|---|---|---|
| 服务端 BossAgent_Rule 增删改 | 项目只 get 读,从不写 | 服务端改了 → 本地需手动 pull 才生效 |
| 本地管理界面 saveRule | 是,写 BossAgent_Rule | 引擎建时传 SCSAIClient 即生效 |
| 本地管理界面 deleteRule | 是(走 SCSAIRuleSync) | 同上 |
| sync-rules-SCSAI-to-local.js | 只读 pull | 幂等覆盖,会覆盖本地未上 SCSAI 的修改 |
注意:pull 用 item_number 幂等覆盖。若本地有 manual 修改但 SCSAI 端没有对应 item,重跑 pull 不会删除本地多余规则,但会覆盖同名规则——本地独占修改有被覆盖风险,建议通过 push 先上行。
5. 运维要点
- 首次/定期对齐:跑
--both做一次双向收敛。 - 确认同步率:查
sciot_rules_v2中SCSAI_id非空的条数;正常应接近本地非垃圾规则总数。 - 孤儿规则:
id IS NULL的本地规则无法 push,需先赋予语义化id(如biz-repair-xxx-001)。 - 漂移告警:启动日志搜
[RuleDrift],出现 WARN 即两端分叉,需--both修复。 - 数据质量:
action_config/tags必须是合法 JSON 或 CSV;inspect 类规则的action_config允许key:value文本(引擎有专门解析)。 rule_engine.db是运行时产物,被.gitignore排除;可随时用--both从 SCSAI 重建。
6. 已知遗留
- 本地
source=builtin规则(如BUILTIN-、内置biz-)不回写 SCSAI(设计上 SCSAI 为权威源,内置规则应以 SCSAI 为准)。 - 无自动/定时同步调度;当前依赖启动漂移自检 + 手动
--both。如需常驻同步可加 cron/定时器调用本脚本。 BossAgent_Prompt/BossAgent_Template/BossAgent_BizPrompt的本地副本仍由template-sync-service.js只读拉取,管理界面修改暂不回写 SCSAI(独立待办)。
BossAgents