Skip to main content

Module plugin

Module plugin 

Source
Expand description

§6 plugin contract & dispatch — subprocess-uniform.

A plugin is a single binary, invoked identically whether it is one of the shipped capabilities or a third party: there is no in-process path and no privileged plugin. balls spawns <bin> <op> <phase> with the §7 payload on stdin and the §6 env set, and reads NOTHING back — a plugin contributes by editing the change worktree, never by printing values (§7, no return channel). The plugin stays DUMB about diagnostics too: it writes raw stderr and is told nothing about where it lands (no BALLS_LOG_DIR — a new env is a §0 smell); balls pipes the child’s stderr and ENVELOPES each line as a record into the unified op log (src=<name>, lvl=info). A non-zero exit aborts the op — core emits an error record naming the locus first — and the crate::lifecycle engine then rolls the prior plugins back in reverse.

Subprocess is the production Plugins seam. It is built once per op with the op-constant OpContext (the §7 wire data the verb layer authored), the op’s Log sink (it logs each invoke and envelopes plugin stderr), and the recursion depth balls is running at. The engine hands it the per-phase post-seal Sealed facts.

Recursion guard (§6, bl-7110). A plugin may shell back to bl; every nested call bumps BALLS_PLUGIN_DEPTH. Crossing DEPTH_CAP ABORTS the op — fail, not silent: Subprocess::run returns an error naming the op/phase that overran, so the crate::lifecycle engine rolls the prior plugins back in reverse (§8/§14) and the runaway SURFACES. There is no hatch to re-enable plugins on a nested call — that would let a runaway defeat its own backstop. rollback cannot spawn at the cap either, so it no-ops (best-effort, §14).

Structs§

Protocol
A plugin’s self-description from <bin> protocol: the protocol version(s) it speaks and the ops it handles. balls never persists it — it is read at install time to validate a binding, and is diagnostics otherwise (§6).
Subprocess
The production Plugins seam: spawns each plugin as a subprocess with the §7 wire on stdin (§6). Borrows the op’s Log for the run’s lifetime — it shares the one per-clone sink with core’s own lifecycle records.

Constants§

DEPTH_CAP
The built-in recursion cap (§6, bl-7110): reaching this depth ABORTS the op.

Functions§

describe
Run <bin> protocol and parse its { protocol, ops } self-description (§6). A spawn failure, a non-zero exit, or unparseable JSON is an io::Error.