feat(tui): generate KeybindingsManagerCore handle class via fluessig#311
Conversation
Conformance smoke: agent + ai + tui
Headline is rust-backed: passing cases in files whose module-under-test is a native (Rust addon) module. Raw all-pass is shown secondary — it is inflated by unflipped TypeScript that passes without touching any Rust.
agent: 73/180 (40.6%) · ai: 81/1296 (6.3%) · tui: 375/678 (55.3%) rust-backed = passing / total tests run, per the manifest's per-native-row AttributionA pi test file is rust-backed iff the module it primarily exercises — its module-under-test — is Per-file decisions (from each native manifest row's
CLI conformance (black-box, against the pidgin binary)
The four repointed coding-agent CLI test files spawn the compiled pidgin binary via |
6b9ecfe to
396d767
Compare
18158ba to
e549210
Compare
Swap the hand-written `#[napi] pub struct KeybindingsManagerCore` (backing
`packages/tui/src/keybindings.ts`) for a fluessig-generated handle class —
the first opaque-handle (`Shape::Ctor`) swap in the campaign. The class is
authored as a ctor interface in `schema/api.json`: a `ctor` op plus four
`unary` methods (`matches`, `getKeys` infallible; `getConflictsJson`,
`getResolvedBindingsJson` fallible). `regen.sh` (fluessig pinned at 1fed77a)
lowers it to `#[napi] pub struct { core: Arc<KeybindingsManagerCoreImpl> }`
with the ctor building the core via the generated `KeybindingsManagerCoreCore`
trait and each method delegating through `self.core`.
The engine seam lives in `src/core_impl.rs`: `KeybindingsManagerCoreImpl`
wraps one immutable `pidgin_tui::KeybindingsManager` and routes to the SAME
resolution logic the hand-written class called, reproducing its exact JSON
parse-error messages via `anyhow`. The hand-written struct/impl and its two
input DTOs are deleted from `tui_components.rs`.
This proves the `Shape::Ctor` handle path end-to-end — no fluessig codegen
gap. The generated `.d.ts` is whole-file byte-identical to the pre-swap
baseline; the class's `.js`/`nativeBinding` entries are byte-identical (the
symbol relocates from the lib.rs tail into the generated export block, as
every prior swap did). The `test/keybindings.test.ts` oracle passes 4/4
against the locally built addon.
396d767 to
318fdb9
Compare
What
First opaque-handle class swap in the pidgin-napi → fluessig campaign: moves the hand-written
#[napi] pub struct KeybindingsManagerCore(backingpackages/tui/src/keybindings.ts) onto the fluessig-generated napi surface. This is the strategic prove that fluessig'sShape::Ctorhandle-lowering path works — the biggest remaining bucket (~79 of ~166 exports are handle-class methods).Stacked on
napi-fluessig/tui-utils(the current stack tip; the task's "module5" name maps to it).Before / After
Before — hand-written in
lib.rs:After — authored as a
ctorinterface inschema/api.json(ctor op + 4 unary method ops), regenerated byregen.shintosrc/generated.rsas#[napi] pub struct KeybindingsManagerCore { core: Arc<crate::core_impl::KeybindingsManagerCoreImpl> }with the ctor building the core via the generatedKeybindingsManagerCoreCoretrait and each method delegating throughself.core. The engine seam (KeybindingsManagerCoreImpl) lives insrc/core_impl.rs, wrapping one immutablepidgin_tui::KeybindingsManagerand routing to the same resolution logic — reproducing the hand-written JSON parse-error messages viaanyhow. The hand-written struct/impl + its two input DTOs are deleted fromlib.rs.How
KeybindingsManagerCore— the simplest immutable Bucket-D handle: all-primitive carriers (string / bool /Vec<string>), a plain concreteinner(no generic host provider, no fs/exec side-effects), truly&self-immutable, dedicatedstatus=nativeoracle.Shape::Ctorpath worked end-to-end — no fluessig codegen gap. fluessig (pinned1fed77a) lowered the ctor interface to theArc<…Impl>handle class +…Coretrait exactly as the reference backend prescribes; ctor via<Impl as Trait>::new(...).map_err(err)?, method arms honoring infallible (-> T) vs fallible (-> Result<T>) and the js-name pins.Gates
.d.ts: whole-file byte-identical to the pre-swap baseline. The class block (JSDoc + all 5 members) matches exactly..js: class entries byte-identical.module.exports.KeybindingsManagerCore = KeybindingsManagerCoreis byte-identical text; the only delta is the symbol relocating from thelib.rstail into the generated export block (every prior swap did the same — napi ordersindex.jsby crate registration order).cargo build -p pidgin-napi,cargo fmt --all --check,cargo clippy -p pidgin-napi --all-targets -- -D warnings— clean. codespell 0.git archive HEAD: 877 files, 0 errors, 1conformance/STEWARD.mdslop-prose WARN (pre-existing, allowed).packages/tui/test/keybindings.test.tsagainst the locally built addon: 4/4 pass.🤖 Generated with Claude Code
https://claude.ai/code/session_017xL2W7dkhPsTSRuXQNCDeY
Generated by Claude Code