| name | henji-application-capability |
| description | 为 Henji-AI 新增、修改或迁移应用能力,并完成智能助手原生适配。新增或调整工作区、页面、浮层、工具箱工具、设置项、用户可查询数据、业务操作、稳定引用、权限、宿主上下文、能力搜索,或清理旧 HostCommand/HostQuery/Agent 工具时必须使用。 |
痕迹AI 应用能力适配
把应用功能注册成智能助手可按需发现、受控执行、能够验证的原生能力,不新增兼容工具路径。实体与属性以 Application Control 反射注册表为唯一真相源;无法用 CRUD 表达的算法操作以 ApplicationCapabilityDefinition 为唯一真相源;两个以上应用操作由 run_henji_script@1 解析为同一 Application Control 执行内核,不再建立第二套编排协议。
执行流程
0. 先判断该不该写专用能力
默认不写。 反射层已经提供三个通用动词,领域只要注册实体和属性,助手就能用:
| 需求 | 做法 |
|---|
| 读某个状态 | 注册实体和属性即可,list_application_entities / read_application_entity 自动可用 |
| 改某个已有对象的属性 | 注册属性并实现 ApplicationMutationExecutor,change_application_entities 自动可用 |
| 新增或删除集合成员 | 实体描述里声明 collectionWrite,实现 ApplicationCollectionExecutor |
| 带算法的语义操作 | 才写专用 ApplicationCapabilityDefinition |
静态属性与 collectionWrite 只表示“结构上支持”。每个 provider 还必须通过 getPropertyAvailability / getCollectionAvailability 返回当前引用、模式和状态下的真实可用性;没有额外集合限制时复用 unrestrictedCollectionAvailability。计划、提交预检和每步执行前由统一事务引擎复核,领域服务里不再复制模式守卫。
describe_application_entities 可带 refs 查询实例级动态状态。recovery 只放结构化能力/实体/属性标识;任何操作步骤必须先通过正式 describe → change → read/真相源 结果测试,禁止凭读代码猜一条路线写进提示或错误。
只有当动作无法用属性写入表达时才写专用能力——例如"环绕运镜"要按角度采样算轨迹,"复用或布置对象"要做碰撞检测和复用判定。凡是"设置某某值""加一条记录"这类,一律走通用动词。
Camera Stage 只公开 camera_stage.state_keyframe。动画操作必须走已经过结果测试的路径:在同一次 change_application_entities 的 changes 中按顺序交替写 camera_stage.playback.current_time 与对象、角色或摄像机的 animatable.* / pose_preset,最后可在同一事务写 loop/playing;应用会自动创建或更新完整场景状态,任一步失败则整体回滚。除非后一步需要前一步新创建且尚未返回的引用,否则禁止按时间点拆成多轮调用。派生属性轨道只供播放与导出,不能注册为公开实体或持久化真相源。
两个以上应用操作统一交给模型可见的 run_henji_script@1。先从能力发现读取本轮 scriptApi 租约,再用 app.entities / app.action / app.recipe / app.assert 组成一段 henji-ts/v1;版本、revision、完整引用和数据依赖全由宿主处理。源码只用 TypeScript Compiler API 解析为自有 IR,永不执行 JavaScript。禁止语法、未租赁 API、截断引用和超限操作必须在首次 Gateway 写入前拒绝。
首次能力发现必须把渲染层真实反射注册表合并进 scriptApi:实体、属性、enum、数值范围、引用形状、nullable、写 operation、集合父类型和必填属性都由注册表投影,禁止让模型猜值或在提示词复制第二份 schema。编译预检要检查所有静态候选值,包括 if/else 和三元分支;任一候选不合法时 Gateway 调用数必须为 0。
高频且参数形态稳定的任务应增加 Henji Recipe:模型只提供业务参数,Recipe 展开为同一份 IR,不拥有第二套解释器、Effect、补偿或验证逻辑。配方里的每条路径必须先通过真实 Registry、Gateway、领域执行器和正式状态源的结果测试。
Henji Script 引导分层固定如下: system prompt 只放“必须先发现、应用操作只经 run_henji_script”等不可选协议;工具契约声明受限语言与安全边界;首次发现的 scriptApi 动态给出真实 API/schema;软件内置领域 skill 只给业务选择和已验证 Recipe。本项目开发 skill 只指导如何接入这些层。不要新增泛化的 Henji Script 教程 skill,也不要把领域 action 参数复制进 system prompt——语法和 API 必须由工具与 scriptApi 自描述,避免版本漂移和 skill 未触发时出现旁路。
声明了可写属性就必须注册 ApplicationMutationExecutor,声明了 collectionWrite 就必须注册 ApplicationCollectionExecutor。每个实体必须至少拥有一种写入执行器,或填写 writeExclusion.reason,明确说明为何只读以及状态由哪个正式模块或操作维护;不得用“暂时不支持”代替判断。三者由覆盖测试强制一致。
新增可写属性只在一处声明。 一个属性此前要碰 4 个位置(属性描述符、读取映射、写入表项、界面动作账本),缺任何一处都是静默失效——不报错,助手安静地少一块能力,只有用户实机撞上才发现(三维场景外观 24 项当初就是这样漏掉描述符和读取两处)。现在统一走 src/core/application-control/fieldDefinition.ts 的 ApplicationFieldDefinition:
sceneField('sky_color', '天空颜色', COLOR, {
read: (settings) => settings.sky.color,
write: (store, value) => store.setSceneSkyColor(value),
storeAction: 'setSceneSkyColor',
})
一条声明用 fieldDescriptors() / fieldReadValues() / fieldWriterTable() / fieldLedgerEntries() 派生出描述符、读取映射、写入表项、账本条目四样东西,四个消费方各取所需。字段定义按领域收在 <领域>Fields.ts(如 cameraStageSceneFields.ts、canvasFields.ts、assetFields.ts),领域内部再包一层 <领域>Field() 薄封装填好该领域固定的 entityType、权限、revision scope。同一个 store 动作被多个字段共用时(如 updateObject 一次改 name/visible/color/character_variant 四个属性),fieldLedgerEntries() 按声明顺序把它们累进同一条账本绑定。禁止再分别手写这四处——统一定义之后漏一条是整条从四处一起消失,会被 storeActionCoverage 门禁当场抓到,而不是像以前那样只漏两处却全绿。
1. 判断能力边界
- 先定位正式业务服务,禁止让能力处理器复制业务逻辑。
- 专用能力与通用动词同时触达同一状态时,两条路径必须委托同一个正式业务服务。
- 判断执行位置:依赖 DOM、当前页面轻状态或即时视觉反馈时放渲染层;文件、数据库、网络、复杂计算、长耗时任务或系统权限放主进程。
- 将一个算法能力限定为一个可验证动作。确有预览/审批语义的查询、计划、提交可注册成独立原子 action,再由同一 Henji Script 编排;这不是让模型拆成多轮。禁止用一个开放参数工具承载任意操作。
- 后台能够完成的操作不要切换页面;只有用户明确要求查看、定位或进入编辑器时才使用 Surface 能力。
- “不要切换/不要删除”等负向约束由 Gateway 与审批边界承担;最终说明须用 Effect Receipt 反查这类事实,禁止否认已经发生的副作用。
2. 定义原生能力
- 实体、属性和集合 CRUD 在 Application Control 反射注册表中声明,由通用
app.entities API 投影;不得为它们再写同义的专用能力。
- 只有无法用 CRUD 表达的算法操作,才在
src/core/assistant/ 的领域能力模块中声明 ApplicationCapabilityDefinition 并注册到统一目录,由 app.action 调用。
- 使用稳定、小写的能力 ID;版本从 1 开始,破坏性契约变化才升级版本。
- 完整声明输入/输出 schema、AI 输入 schema、领域、别名、读写属性、风险、数据等级、权限、超时、幂等、撤销、预览、作用域、可用条件、前置能力、并发键、引用类型、成功证据和失败恢复。
- AI 输入 schema 顶层必须
additionalProperties: false,禁止开放 patch、storePatch、executeScript、script 等任意 Store Patch 或代码入口。只有 run_henji_script@1 可以声明 source,且只能解析受限 IR。
- 用户化描述只说明用途和影响,不写协议名、schema、revision、风险编号或开发解释。
- 输入和输出优先传
ApplicationRef;禁止传原始密钥、本地路径或不受控的大对象。
- 写能力必须绑定相关 scope revision;未知副作用的写操作禁止自动重放。
详细字段选择和范式见 references/capability-patterns.md。
3. 绑定执行处理器
- 由所属功能模块注册处理器,不把新处理器继续堆进全局 command/query 执行表。
- 使用通用 capability 信封执行,禁止新增
kind: 'command'、kind: 'query'、HostCommand 或 HostQuery 分支。
- 执行前由统一入口校验版本、输入、权限与 expected revisions;执行后校验输出 schema 和成功证据。
- 关键链路在实际执行层记录
start、completed、failed,日志只记录稳定引用和脱敏信息。
- 页面尚未打开时也应能调用正式业务服务;确实依赖可视编辑器时,在
availability 和前置条件中明确声明。
4. 接入按需发现
- 为能力提供用户可能使用的中文、英文和领域别名。
- 声明
acceptsRefs、producesRefs 和前置依赖,让跨模块任务通过稳定引用衔接。
- 不把全部能力注入模型;保持每轮最多 32 个、合计不超过 96KB 的活动 schema。发现请求由模型自己写(queries/domains/entityTypes/writes),运行时不改写;租约名额只引用
toolBudget.ts,这些数值只引用 toolBudget.ts,不得在契约或运行时另写一份。
- 发现能力返回
leasedToolNames 与 deferredToolNames/deferredCount。租约工具必须在下一模型步骤真实可用;活动工具已带完整输入 schema,不得在发现后自动调用 read_application_schemas。
- 首次返回的
scriptApi 必须包含租约范围内的真实实体定义和属性约束;后端发现结果必须用渲染层反射 schema 水合后再写入租约缓存,禁止缓存未水合的候选目录。
- Router 只提供页面锚点和搜索建议,不得以分类结果限制能力可用性或授权。
- 写能力必须通过
control.impacts 声明 Effect、实体和属性;一次输出可能影响多个目标时实现 resolveObservedEffects(input, output),从真实结果解析数量、稳定引用和验证证据。没有解析器的能力一次最多贡献一个 Effect。
- 单事务内的多项实体改动由 Henji Script 自动合并到
change_application_entities;跨能力且后一步依赖前一步输出时,直接用脚本变量持有完整稳定引用,不再拆成模型多轮。
- 跨领域结果传递必须注册接收上游稳定引用的正式桥梁能力,并验证它能进入下游能力租约;禁止让模型猜测领域等价物、手工拼接内部路径,或把生成结果冒充素材。媒体 URL/本地路径只在宿主内部组合服务中流动。
- 反射层公开每个可写属性真实接受的
writeOperations;高层集合 set 由计划器确定性编译为 append/remove 最小差异,不支持的操作在计划期拒绝。
- 同一通用事务可以重复写同一属性,最终状态只验证最后一次写入;播放头、播放开关等会话控制声明
verificationStrategy: 'execution',中间状态的真实领域副作用必须由正式结果测试覆盖。
- 后置步骤依赖前序步骤刚建立的动态可用状态时,静态权限仍在计划期拒绝,动态 availability 延迟到该步骤执行前复核,失败由事务补偿。
entityType 与 target.kind 重复表达实体类型时由通用适配器统一规范化;领域 provider 只可在全局唯一时补全短引用,歧义引用继续拒绝。
- 写入触发自动创建/更新等领域级联副作用时,正式执行器必须返回带静态
declarationId 的强类型 Effect Receipt;evidence 只做验证与说明,禁止用它记账或只按输入猜影响范围。
- 工具网关负责把
resolveObservedEffects 的结果固化进 observation;成功封存只消费该字段。执行结果封存后,最终说明模型失败只能降级为 completed_with_warning 和确定性摘要,不得覆盖已经验证的应用成功。
- 外部等待前持久化受控 IR 断点、有限变量、完整稳定引用、Effect Receipt 和验证状态;续接固定先查权威状态,再由同一解释器只执行剩余指令。禁止保存或重放模型源码,禁止从摘要/任务 ID 重建;断点缺失或摘要不匹配必须在后续写入前阻断。
- 封存点是「模型自己决定收工」:本轮不再调工具、给出最终答复,且有真实写入 Effect、运行客观上已经停下来。不得在模型请求前用任何预测判它做完了并撤掉工具——模型可能正知道还差一步。每项 Effect 的
targetRefs 必须来自真实执行输出,保持完整稳定引用。
- 拒绝必须能被自我修正:实体类型写错就列出该域注册了哪些,属性写错就列出这个实体有哪些,参数被静默丢弃就说清丢了哪些键与可用的是哪些。只给错误码等于逼模型继续猜,而它猜不中就是死循环。
- AI 可见输入 schema 不暴露
baseRevision / expectedRevisions。并发基线只由 Gateway expected-revision 信封传入,兼容字段只能校验一致性,不能形成第二条 revision 路径。
5. 覆盖新功能
优先用通用动词覆盖(见第 0 节);只有算法型语义操作才注册专用能力。
新增或修改下列对象时,注册能力或加入带原因的显式排除清单:
- 工作区、工具页、设置页和浮层。
- 工具箱工具和用户可触发的业务动作。
- 设置项及其读取、计划、提交能力。
- 生成记录、素材、项目、节点等用户可查询数据。
- 可在模块间传递的实体引用。
- 公开实体、属性、语义操作、验证方式和 Surface 观察策略;漏登记必须由
check:assistant-capabilities 或覆盖测试阻断。
不得因为“暂时没有助手需求”而省略覆盖判断。
6. 迁移旧工具
- 将旧 Agent 工具的 schema、权限、语义和执行行为迁入原生定义及模块处理器。
- 同一模块迁移完成后立即删除对应旧工具、HostCommand/HostQuery 分支和旧处理器,禁止保留双实现。
- 保留审批、revision、撤销、幂等、并发、脱敏和结果真实性语义。
- 全部迁移后删除兼容描述生成器、旧 operation 分支以及 v2 快照中的
availableCommands/availableQueries;旧 v1 保存点只允许由集中、只读适配器映射为 availableCapabilities。
7. 验证
- 运行能力覆盖检查,确认定义、处理器、Surface、设置和工具覆盖一致。
- 新增或改造 Surface 时必须在统一目录声明观察提供者、捕获策略、数据等级、遮罩策略、支持模态、尺寸预算和失效条件;不允许留下无理由的观察空缺。
- 观察提供者、数据等级、遮罩策略和支持模态只在
resolveSurfaceObservationProfile 判断一次,目录和覆盖清单都从它派生;界面标注 Surface ID 时从目录反查,不在组件里复制映射表。
- 观察默认走
target="window" 整窗,任何时候都可用;只在需要聚焦时传具体 surfaceId。截图范围永远只有本应用窗口,禁止桌面和其他应用窗口。
- 遮罩只认显式的
data-observation-sensitive。新增界面时,凡是把明文本地路径、密钥或令牌渲染出来的节点都要自己标上;type="password" 的输入框自带圆点掩码,不需要标。
observe_application_surface 是唯一把像素送进模型的观察入口。不要新增只返回媒体引用或“已截图”标记的观察能力——模型看不到画面却会以为看过了;要产生视觉证据就返回 verificationKind: 'visual_pending_model' 加合法附件。
- 空间类写入(三维、画布布局)必须配一个结构化验证能力,并在同一段脚本里读回验证;视觉证据是加成,不能替代结构化验证。
- 视觉观察优先使用领域结构化状态或稳定原生媒体,其次使用专用视口,最后才允许捕获已注册的应用内区域;禁止回退为系统桌面、其他窗口或整屏截图。
- 观察结果只有被主模型或观察模型实际读取后才能标记为视觉验证;只有结构化证据或模态不可用时必须分别标记,不能把媒体引用文本当作已读取内容。
- 为每项能力验证合法输入、非法输入、权限、revision 冲突、成功证据和失败恢复。
- 每个拥有 mutation/collection 执行器的写域登记 2–3 条结果场景;必须从正式状态源或
readEntity 断言世界真的变化,completed 或 evidence 不算结果断言。
- 验证注册 100 项能力时初始上下文仍精简,活动工具不超过
toolBudget.ts 声明的上限。
- 涉及跨模块任务时验证稳定引用传递,不得通过名称猜测或原始路径衔接。
- 运行相关 Agent 测试、TypeScript、Lint 和 Electron 构建检查。
- 涉及鼠标交互时只写清用户手动验证步骤,不代替用户操作界面。
完成标准
- 能做的事优先通过通用动词暴露;专用能力只用于无法用属性写入表达的算法型操作。
- 声明
collectionWrite 的实体类型都注册了 ApplicationCollectionExecutor,由覆盖测试拦截。
- 每个 provider 都实现动态集合可用性;模式限制可在 describe 阶段看见,并由事务引擎统一执行。
- 每个实体都有 mutation/collection 执行器或非敷衍的
writeExclusion.reason;新增实体后运行 npm run check:assistant-capabilities。
- Application Control 反射注册表是实体、属性和集合 CRUD 的唯一元数据源;
ApplicationCapabilityDefinition 是算法操作的唯一元数据源;scriptApi 只能投影两者,不能成为第三份手写 schema。
- 正式业务服务是唯一业务执行源。
- 普通界面不显示开发性解释。
- 新代码没有旧 command/query 兼容路径。
- 新代码没有任意 Store Patch、任意脚本执行或 Application API 核心跨层导入。
- 权限、revision、日志、引用和成功证据均有自动化验证。