Rule
Rule 规范
Rule 是什么?
Section titled “Rule 是什么?”Rule 是 Proto UI 中表达“当某些条件成立时,产生某种明确意图”的声明式语法。它不是信息通路,也不直接在 Component、User、App Maker 或其他 Component 之间传递信息。
Rule 的价值在于把原型作者的意图保留为可分析结构。命令式 callback 可以表达很多同类逻辑,但 adapter 很难稳定理解那段代码想做什么;Rule 则把条件和意图拆开,使 adapter 有机会在不依赖 compiler 级静态分析的情况下做优化。
Rule 是可选语法。砍掉 Rule 不应让原型失去表达同类行为的能力;但当逻辑本来就能清晰写成“条件成立则产生意图”时,Rule 是官方推荐路径。
setup-onlyRule 的声明发生在 setup 期:
def.rule(({ when, intent }) => ({ when: when.eq(when.props('disabled'), true), intent: intent.feedback.style.use(tw('opacity-50')),}));def.rule(spec) 只记录 when 与 intent。它不会在 setup 期读取当前 runtime props,不会写 state,不会写 feedback,也不会触达 host。
setup-only API 返回的移除或撤销函数默认也只能在 setup 期使用。Rule declaration 的移除能力如果存在,也不能被闭包保存到 runtime 里作为 lifecycle disposer 或 escape hatch。
runtimeruntime 期会根据当前可观察输入评估 RuleIR,选出 active Rule,按声明顺序收集 intent,并产出 semantic Plan。v0 稳定默认 Plan 是 style.tokens。
默认 runtime 执行路径不直接写 DOM class、attribute、native view 或其他宿主对象。adapter 或扩展模块可以 short-circuit Plan,生成更适合宿主的优化产物,但优化产物不能反过来定义 Rule core 语义。
when 是纯条件表达式。它读取其他模块提供的可观察输入,并产出 boolean。
v0 核心表达式包括:
truefalseeq(a, b)not(expr)all([...exprs])any([...exprs])eq 使用严格相等,不做隐式类型转换、深比较或自定义 comparator。all([]) 是 true,any([]) 是 false。
Rule 不直接匹配瞬时 event occurrence。事件驱动的 Rule 需要先把事件维度表达为可观察状态,例如 hover、pressed、focused 这类 interaction state,然后由 Rule 读取状态。
when 输入来源
Section titled “when 输入来源”Rule core 不创造输入源。when 中的 props、state、context 或其他输入,都必须由对应模块或 rule 扩展提供。
稳定的核心覆盖包括:
| 输入来源 | 当前语义 |
|---|---|
props | 读取 resolved props,依赖 prop identity,prop 变化可触发重评估 |
state | 读取 state view 当前值,Owned / Borrowed / Observed 都可被观察 |
context | 读取整个 context value;不存在 provider 时为 null |
context path access 仍是实现债。当前核心契约只固化 whole-value context dependency,不把 w.ctx(key).path(...) 当作稳定 v0 语义。
host/environment 输入目前也不归入稳定核心命名。现有 meta 相关实践属于二级或待治理抽象,未来可能被更系统的环境配置模型替代。
intent
Section titled “intent”intent 记录可分析操作,而不是在 setup 期执行操作。它不能携带任意 callback,也不能把宿主命令式逻辑塞进 RuleIR。
不同 intent channel 的合并与执行语义由各自契约定义。Rule core 不提供隐式跨通道优先级。
feedback.style intent
Section titled “feedback.style intent”v0 稳定的 Rule intent 是 feedback.style:
def.rule(({ when, intent }) => ({ when: when.eq(when.state(pressed), true), intent: intent.feedback.style.use(tw('translate-y-px opacity-80')),}));i.feedback.style.use(...handles) 记录视觉反馈样式意图。它不扩展 feedback.style token 语言,输入仍必须遵守 feedback.style 的 handle 与 token 约束。
active Rule 的 style token 按 Rule 声明顺序收集,然后交给 feedback semantic merge。Rule 失效时,它贡献的 style token 必须在下一次评估中移除。
这条链路可以理解为:
observable inputs -> when evaluation -> active rule intents -> style.tokens plan -> feedback semantic merge -> feedback runtime style layer -> translation layerRule 产出的是可翻译 style 语义结果,不是 DOM class 或 CSS selector。Web selector 优化是 Rule 思路的一个下游成果,但不是 Rule core 的设计约束。
Deferred Scope
Section titled “Deferred Scope”以下内容已经记录为断口或实现债,但不属于当前稳定 v0 Rule core:
| 项目 | 状态 |
|---|---|
intent.state | 计划能力;layer stack、rollback、baseline、reason 等语义尚未实现为 v0 保证 |
| context path access | 当前只稳定 whole-value context dependency |
meta 命名 | host/environment 输入的抽象层级和命名仍待治理 |
| RuleIR live handle side table | 需要继续收敛实现,避免 RuleIR 携带 live handle |
| setup-time removal handle | 需要确保 setup-only removal 不变成 runtime disposer |
这些项目可以被 fixture 或 planned test 看见,但不得被视为当前 required matrix 覆盖。
契约实体预览
Section titled “契约实体预览”与测试的关系
Section titled “与测试的关系”Rule 的测试实体按“维度测试 + 矩阵测试”组织,避免组合爆炸:
| 测试实体 | 主要覆盖 |
|---|---|
T-RULE-0001 | def.rule setup-only、RuleSpec recording、RuleIR serialization、setup-only removal |
T-RULE-WHEN-0001 | when 纯表达式、严格相等、逻辑表达式、event 边界 |
T-RULE-WHEN-0002 | props/state/context 依赖维度 |
T-RULE-INTENT-0001 | intent operation recording 与 channel independence |
T-RULE-INTENT-FEEDBACK-STYLE-0001 | 稳定的 feedback.style intent |
T-RULE-MATRIX-0001 | props/state/context × feedback.style stable matrix |
intent.state 的组合可以出现在 matrix fixture 中,但它是 deferred cell,不是当前 required coverage。
与其他规范的关系
Section titled “与其他规范的关系”Core定义 setup/runtime 阶段边界;Rule 声明遵守 setup-only,Rule evaluation 发生在 runtime。Props、State、Context可以为when提供可观察输入,但 Rule 不拥有这些信息来源。Event不被 Rule 直接匹配;事件维度应先进入可观察状态。Feedback定义feedback.style的 token 与 semantic merge;Rule 的稳定 v0 intent 复用这套语义。Lifecycle管理实例存活与 runtime callback 边界;Rule 的 setup-time removal 不能变成 lifecycle disposer。Adapter与 rule extension 可以做优化,但必须保持默认 Plan 的语义等价。