Problem Statement
OpenLark 的编译能力目前由 Cargo feature、Client 字段与构造声明、registry 元数据、bootstrap cfg 列表和 FeatureLoader 分别描述。它们表达同一事实却没有 locality:bot 已经从 registry 目录漏掉,ai 的声明依赖与实际编译依赖不一致;registry interface 还宣称能返回 typed instance 和生命周期状态,但所有编译条目的 instance 都是 None。使用者无法把 Client::registry() 当成编译能力的可信来源,维护者新增业务域时必须跨多个 module 手工同步。
Solution
把编译可用性、Client 字段构造和诊断元数据合并到一个不可变的 compiled-capability catalog module。该 module 继续使用零成本的编译期生成,registry 保持纯元信息诊断用途;不存在的 typed-instance 和生命周期知识从 interface 删除,FeatureLoader 的重复入口被吸收。
User Stories
- As an OpenLark user, I want
Client::registry() to report every compiled capability, so that diagnostics match the client I built.
- As an OpenLark user, I want disabled capabilities absent from the catalog, so that runtime reporting matches Cargo features.
- As an OpenLark bot user, I want the bot capability represented when compiled, so that diagnostics do not omit a usable client field.
- As an OpenLark AI user, I want reported dependencies to match actual feature dependencies, so that catalog information is trustworthy.
- As an OpenLark library user, I want metadata queries to succeed without implying runtime instances, so that the interface does not promise impossible behavior.
- As an OpenLark SDK maintainer, I want one declaration to generate client construction and metadata, so that new domains require one change.
- As an OpenLark SDK maintainer, I want compile-time generation preserved, so that no dynamic service locator or downcast cost is introduced.
- As an OpenLark test author, I want feature-matrix contract tests, so that catalog and Client fields cannot drift.
- As an OpenLark docs author, I want capability names and descriptions sourced from one catalog, so that documentation does not fork from runtime diagnostics.
- As an OpenLark operator, I want deterministic immutable metadata, so that diagnostics cannot expose meaningless lifecycle mutations.
- As an OpenLark maintainer, I want duplicate bootstrap paths removed, so that initialization has one implementation.
- As an OpenLark downstream user, I want existing metadata listing and presence checks preserved, so that useful diagnostic code remains compatible.
Implementation Decisions
- A single immutable compiled-capability catalog is the source of truth for feature name, Client field construction, diagnostic name, description, dependencies, provided capabilities, and priority.
- Macro generation remains compile-time and zero-cost; no runtime plugin container,
Any downcast, or dynamic dispatch is introduced.
Client::registry() remains the external diagnostic seam.
- Registry entries remain metadata-only. Typed-instance lookup, mutable lifecycle timestamps, and status transitions are removed from the public interface unless real instances and adapters exist.
- The async FeatureLoader pass-through and duplicate bootstrap entry are removed or reduced to generated catalog consumption with no unused configuration argument.
- Catalog dependencies must match Cargo feature relationships exactly; catalog presence must match Client field presence for every feature combination covered by CI.
- Existing useful listing, lookup,
has_service, description, dependency, capability, and priority behavior is retained through the smaller interface.
- This deepens the macro-driven decision from the archived architecture audit; it does not reopen the rejected runtime service-container design.
Testing Decisions
- The highest runtime test seam is
Client::registry() on clients built under representative feature sets.
- Compile-time feature-contract tests prove that each enabled Client field has exactly one catalog entry and each disabled feature has none.
- Tests explicitly cover bot presence, AI dependency truth, duplicate-name rejection at generation time, stable ordering, and metadata completeness.
- Tests assert public catalog results rather than generated macro internals, bootstrap helpers, or mutable registry state.
- A no-default-features build and the full feature build are mandatory test modes; representative single-domain builds cover conditional generation.
- Prior art is the repository's feature-contract tests and current registry listing examples, moved to the immutable catalog seam.
Out of Scope
Further Notes
- Recommendation strength is Worth exploring because the catalog seam is useful, but the work must preserve the accepted metadata-only registry decision.
- The deletion test proves FeatureLoader is shallow while the catalog earns its depth: deleting the catalog would spread capability truth back across every generated consumer.
Problem Statement
OpenLark 的编译能力目前由 Cargo feature、Client 字段与构造声明、registry 元数据、bootstrap cfg 列表和 FeatureLoader 分别描述。它们表达同一事实却没有 locality:
bot已经从 registry 目录漏掉,ai的声明依赖与实际编译依赖不一致;registry interface 还宣称能返回 typed instance 和生命周期状态,但所有编译条目的 instance 都是None。使用者无法把Client::registry()当成编译能力的可信来源,维护者新增业务域时必须跨多个 module 手工同步。Solution
把编译可用性、Client 字段构造和诊断元数据合并到一个不可变的 compiled-capability catalog module。该 module 继续使用零成本的编译期生成,registry 保持纯元信息诊断用途;不存在的 typed-instance 和生命周期知识从 interface 删除,FeatureLoader 的重复入口被吸收。
User Stories
Client::registry()to report every compiled capability, so that diagnostics match the client I built.Implementation Decisions
Anydowncast, or dynamic dispatch is introduced.Client::registry()remains the external diagnostic seam.has_service, description, dependency, capability, and priority behavior is retained through the smaller interface.Testing Decisions
Client::registry()on clients built under representative feature sets.Out of Scope
Further Notes