本节摘要:技能库让能力可发现、可组合、可审计;安全锁让危险能力不被滥用。本节设计技能注册表(发现、版本、依赖),把宏技能与飞行程序库对齐成程序记忆,制定权限分级与最小权限原则,落实危险动作的沙箱与人工双确认,并以权限矩阵演练收尾——能力越大,闸门越多。
航空外挂物走标准化路线,是被混编机群逼出来的:不同厂家、不同批次的飞机要能挂同一族外挂,靠的是各机队共享的军械登记与审批制度——什么型号、什么挂架许可、什么条件下允许投放,登记在册、审批在先。技能库要解决的是同一件事的组织学问题:外挂多了之后,谁能找到它们、谁能组合它们、谁批准危险动作。注册表管找到,宏技能管组合,权限与沙箱管批准——三件事合起来,就是外挂舱的安全锁。
注册表是技能库的户口系统。每件登记的技能带名称、版本、描述、依赖清单与状态(可用、降级、停用);发现接口按用途检索——规划舱要完成"清点库存"的任务,检索"库存"命中查询类技能。版本纪律与 6.1 的清单一致:破坏性变更升主版、旧版留过渡期。依赖清单值得多说:宏技能依赖底层工具,底层工具升级时,注册表能反查"哪些技能会受影响"——这是变更影响分析的地毯,没有它,一次外部接口升级就能悄悄弄坏一串上层技能。
单个工具解决单步动作,真实任务需要组合——"补货"等于"查询库存 + 生成订单 + 校验预算 + 提交订单"。宏技能把常用组合预制成一条可复用的技能:带自己的清单(参数、权限、超时按子步骤合成)、自己的失败语义(哪步失败可重试、哪步必须回滚)。它与 3.3 节的 HTN 方法库是同一枚硬币:方法库管"任务怎么拆",宏技能管"工具怎么拼",两者都是第 5 章说的程序记忆——飞行器会过的套路,存在库里,用时展开。
组合的纪律是失败语义显式化:组合里每个子步骤标注可重试性(查询类天然幂等可重试;下单类必须带幂等键;已提交的支付类失败要走补偿而不是重试)。没有失败语义的组合是定时炸弹——第二个子步骤失败后从头重跑,第一单已经下了。
权限模型按副作用分级,等级与动作门槛一一对应:
| 等级 | 副作用 | 门槛 | 例 |
|---|---|---|---|
| 只读 | 无状态变更 | 自动放行,记审计 | 查询库存、读天气 |
| 写入 | 可撤销的状态变更 | 校验 + 审计,限频 | 写缓存、建工单 |
| 危险 | 不可逆或外部影响大 | 沙箱预演 + 人工双确认 | 下单、支付、删除、移动实体 |
最小权限是配置纪律:每个任务只授予完成它所需的最低等级,按任务动态借权、任务结束回收,不做常备授权。双确认只留给危险级:机器预演(沙箱里跑一遍,看副作用清单)加人工批准(4.4 节塔台频道的"关键点确认"档落地在此),两道闸都过才点火。审批记录进审计日志——谁、何时、批准了什么、依据什么预演结果,全程可追。
from enum import Enum class Perm(Enum): READ = 0 WRITE = 1 DANGER = 2 class SkillRegistry: """技能注册表:发现、版本、依赖、权限闸门。""" def __init__(self, tower, audit): self._skills = {} # 名 -> {manifest, deps, status} self.tower = tower # 4.4 塔台频道:双确认走这里 self.audit = audit def register(self, manifest, deps=()): self._skills[manifest.name] = { "manifest": manifest, "deps": list(deps), "status": "available"} def impacted_by(self, tool_name): """变更影响反查:该工具升级会波及哪些技能。""" return [n for n, s in self._skills.items() if tool_name in s["deps"]] def authorize(self, skill_name, task_ctx): """权限闸门:按等级走不同门槛,最小权限按任务借权。""" skill = self._skills[skill_name] if skill["status"] != "available": return False, "技能停用或降级中" perm = Perm[skill["manifest"].permission.upper()] if perm is Perm.READ: self.audit.append("perm_auto", skill_name) return True, "只读自动放行" if perm is Perm.WRITE: if not task_ctx.has_grant(skill_name): # 按任务借权 return False, "任务未获该写入权限" self.audit.append("perm_write", skill_name) return True, "写入放行,已限频" # 危险级:沙箱预演 + 人工双确认 dryrun = self.sandbox_rehearse(skill, task_ctx.params) ok, who = self.tower.request_confirm( skill_name, dryrun.side_effect_report) self.audit.append("perm_danger", skill_name, confirmed_by=who, dryrun=dryrun.summary()) return ok, "危险级双确认完成" if ok else "人工否决"
沙箱预演是危险级的第二道闸:在隔离环境里用影子数据跑一遍调用,产出副作用报告——会写哪张表、会发什么消息、金额多少。人工批准时看到的就是这份报告,而不是一句干巴巴的"确定要执行吗"。沙箱的隔离要真隔离:网络分段、影子凭证、资源限额——借真凭证跑的沙箱是自欺。
宏技能的组合骨架顺带补齐——失败语义就写在声明里:
class MacroSkill: """宏技能:工具组合 + 每步失败语义 + 补偿路径。""" def __init__(self, name, steps): self.name = name self.steps = steps # (工具名, 幂等?, 失败语义) def run(self, ctx, executor): done = [] for tool, params, policy in self.steps: r = executor.fire(tool, params) if r.get("ok"): done.append((tool, r)) continue if policy is RetryPolicy.RETRY: r = executor.fire(tool, params) # 幂等才敢重试 if not r.get("ok") and policy is RetryPolicy.COMPENSATE: self.compensate(done) # 走补偿回滚 return {"ok": False, "at": tool} return {"ok": True, "steps": len(done)} def compensate(self, done): for tool, r in reversed(done): # 逆序补偿 COMPENSATIONS[tool](r)
安全锁的联调用权限矩阵演练:构造任务与技能的交叉场景,断言每一格的放行/拒绝与门槛记录符合设计;越权剧本专项——只读任务尝试调危险技能、无借权任务尝试写入,全部必须被闸门拦下且留审计。组合技能另跑补偿演练:第二个子步骤失败,补偿路径把系统拉回组合前的状态。
按症状排查:越权调用成功是最严重的一级故障——闸门被旁路(有人绕过 authorize 直接 fire),修复之外必须回溯审计定影响面;审批疲劳(人工确认秒批成瘾)是危险级定得太宽——降级一批到写入级,双确认只留真正的不可逆动作;技能冲突(两个技能同时操作同一资源)查注册表的资源占用声明——冲突声明与并发闸门(6.2)要接上;宏技能僵化(组合步骤与实际流程脱节)走宏技能的版本回归,与飞行程序库同一套配方审计。
⚠️ 常见坑:权限系统做成"文档里最小权限、配置里最大权限"。闸门的强度长在配置与代码路径上,不长在制度文档上——审计日志定期对账,才是权限系统的真实画像。
至此飞行器本体与外挂全部就位。下一章进试飞与验收:工程栈怎么组、仿真测试怎么飞、指标怎么定——交付之前,还剩伦理与责任两道关。