alef-generated-bindings
GitHub管理Alef生成的跨语言绑定代码。指导通过alef.toml配置和Rust源码修改来生成、验证及同步各语言绑定,严禁手动编辑,需原子提交并处理生成冲突。
Trigger Scenarios
Install
npx skills add xberg-io/xberg --skill alef-generated-bindings -g -y
SKILL.md
Frontmatter
{
"name": "alef-generated-bindings",
"description": "Alef-managed generated bindings in packages\/* and binding crates — the regeneration workflow (task alef:generate \/ alef:verify), the alef.toml section layout, the core-side edits that break a regen, and the FFI bridge's JSON marshalling requirement. Load before editing anything under packages\/* or a binding crate, before adding a trait method or extractor, or when regenerating or verifying Alef output."
}
Alef-Generated Bindings
Files under packages/*/ and in the binding crates are generated by Alef — do not hand-edit.
Workflow
- Check
alef.tomlbefore touching anything inpackages/*/or a binding crate - Modify the Rust source or
alef.tomlitself task alef:generate→alef all --clean. This formats via poly as part of the run; there is notask alef:formattask alef:verify→alef verify --exit-codetask e2e:generatethentask e2e:test(ortask e2e:all) to verify behaviour- Commit Rust source +
alef.toml+ regenerated output atomically
The alef:* namespace is exactly: generate, verify, build, sync, docs,
verify:readme-paths, verify:ffi-formats. Formatting is poly fmt / poly lint.
Freshness check
task alef:verify. A hand-rolled git diff over packages/ is under-scoped — generated
output also lands in crates/xberg-py/, crates/xberg-php/, crates/xberg-jni/,
crates/xberg-node/, crates/xberg-wasm/, crates/xberg-ffi/, packages/dart/rust/,
packages/swift/rust/, and e2e/.
Alef tracks both sides under .alef/: sources_hash.cache (input hashes over the parsed
Rust sources) and .alef/hashes/xberg.<lang>.output_hashes (per-file output content hashes).
Neither makes a generated file safe to hand-fix — a regen restores it. Fix alef.toml or the
Rust source, then regenerate and re-verify.
Key alef.toml sections
[workspace],[workspace.sync](version-syncextra_paths),[workspace.docs],[workspace.poly],[workspace.generate][[crates]]— the Rust source crate parsed for type/function extraction, plus[[crates.source_crates]][crates.<lang>]— one table per binding:python,node,ruby,php,elixir,wasm,ffi,go,java,dart,kotlin_android,jni,swift,csharp,zig(each carryingexclude_functions,target_dep_overrides, stubs, …)[crates.e2e]— e2e generation (output = "e2e",[crates.e2e.call.overrides.<lang>])[crates.readme]— README generation (template_dir = "templates/readme",[crates.readme.languages.<lang>])[crates.exclude],[crates.output],[crates.custom_modules],[crates.publish]
There are no [crate], [languages.*], [e2e] or [readme] top-level tables, and
alef.toml declares no rename mappings — the generated Go trait type is
DocumentExtractor, unchanged.
Canonical e2e tasks: task e2e:generate, e2e:build, e2e:test, e2e:all, plus
e2e:verify, e2e:lint, e2e:quick, e2e:lang. Do not add legacy aliases.
Core-side edits that break a regen
- New extractor struct — needs
#[cfg_attr(alef, alef(skip))]on the struct declaration, not the impl block. Without it the regen aborts globally and nothing regenerates, leaving the tree silently stale. Check this first when a regen dies. (36 of the 42 modules incrates/xberg/src/extractors/carry the attribute.) - Binding-facing types must not be
#[non_exhaustive]— alef generatesimpl From<Mirror> for xberg::TheTypewith a struct literal in ~10 binding crates, and#[non_exhaustive]forbids that (E0639). DeriveDefaultfor forward-compat instead. Keep#[non_exhaustive]only on types listed in[crates.exclude]. - A new enum variant on a binding-facing type breaks exhaustive matches across the generated binding crates.
Trait return types crossing the generated FFI bridge
The generated XbergOcrBackendBridge in crates/xberg-ffi/src/lib.rs marshals every
trait method's return value through JSON (218 serde_json::from_str::<xberg::…> call sites
today) and falls back to Default::default() on an uninitialised vtable slot, a failing host
callback, or a null result. Whether a variant carries a payload is irrelevant.
Adding a method to a trait with a generated bridge means its return type needs
Default + Serialize + Deserialize. Unit-only enums included.
crates/xberg-ffi is built by no ci-rust.yaml leg — only publish-path jobs — so
cargo check --workspace cannot fail on it. Verify with the scoped cargo check -p xberg-ffi.
That check rewrites crates/xberg-ffi/include/xberg.h and packages/go/include/xberg.h to
match whatever feature set you invoked it with, which is usually not the committed one. Revert
that churn rather than committing it.
Which alef answered
task alef:generate shells out to the globally installed ~/.cargo/bin/alef, not a
cargo run against a sibling checkout. A source fix there has zero effect until
cargo install --path . --force. Generator fixes ship in order: land upstream → release alef
→ bump the pinned version → regen. Regenerating against a locally modified alef produces a
tree the pinned version cannot reproduce.
Version History
-
d8e4815
Current 2026-08-28 18:30
修正alef.toml结构(移除旧表头,新增crates.e2e/readme等),明确Go类型无重命名映射,更新freshness check逻辑及破坏性变更注意事项。
- 531e0f7 2026-08-20 07:47


