G5 — Plugin host↔plugin contract (the dlopen direction)¶
Registry: UC-ARCH-plugin (complete)
Effort: M · Risk: low
Problem¶
appcompat answers the consumer→library direction (will an app break when a
library it links changes), and the plugin_abi policy downgrades
calling-convention kinds for in-process host/plugin builds. But the actual
dlopen failure mode is a two-sided contract:
- the host resolves a fixed set of entry-point symbols from each plugin it
loads (
dlsym), and - the plugin resolves symbols the host exports back to it.
plugin-check and check_plugin_host_contract now provide the first-class
answer to "does plugin v2 still satisfy host H's required entrypoints?".
Goal & acceptance criteria¶
- [x] An explicit host-contract check: given a plugin (old/new) and a declared
set of required entrypoints (a small manifest, or symbols extracted from a
host binary), report whether the plugin still satisfies the host —
reusing
appcompat's symbol/version resolution machinery in the plugin-load direction. - [x] A runnable workflow/test fixture: a host that
dlopens a plugin, a v1/v2 plugin pair, and anapp-style demo showing the load failure when a required entrypoint is dropped — with an asserted verdict inground_truth.json. - [x] Docs/tests: plugin-system coverage wiring
plugin_abi+ the host-contract check together.
Design¶
- Reuse, don't rebuild:
appcompat.parse_app_requirements()already extracts required (undefined) symbols + version needs from an ELF/PE/Mach-O consumer. A host binary thatdlopens plugins won't list plugin symbols as undefined (they're resolved at runtime), so add a manifest input (--host-contract entrypoints.txt, or--host <binary>for symbols the host exports to plugins) and run the same availability check against the plugin's exports across v1→v2. - CLI: a thin mode on
appcompat(or a smallplugin-checkcommand incli_stack.pystyle) — minimal surface, delegating toappcompat.py. - Verdict: missing required entrypoint →
BREAKING; reuse_compute_appcompat_verdict.
Files & surfaces¶
abicheck/appcompat.py(host-contract input + check),abicheck/cli_appcompat.py(flag), or a newabicheck/cli_plugin.pyregistered per the "Adding a new top-level command" recipe in/CLAUDE.md.examples/caseNN_plugin_host_contract/(host + v1/v2 plugin + README + ground truth).
Tests¶
- Unit: host-contract check over synthetic plugin snapshots (extend
test_workflow_scenarios.py). @pytest.mark.integration: build host + plugin pair, assert load break.
Out of scope¶
Reverse-engineering implicit dlsym(name) string usage from a stripped host
(out of static scope). Versioned plugin ABIs beyond ELF symbol versioning.