ADR-0003: Dynamic Extension Wiring and Subprocess Execution¶
Context¶
Devflow needs to support multiple language stacks (rust, node, python, etc.) without bloating the core CLI binary with language-specific compilation or logic.
Initially, the devflow-core library directly depended on extension crates using hardcoded dispatch tables, which violated the stack-agnostic boundary of the core engine and prevented external developers from writing custom project extensions.
Decision¶
We have decided to formalize an Extension trait and introduce dynamic runtime discovery.
Extension Trait: All extensions implement an
Extensiontrait offeringname(),capabilities(), andbuild_action().devflow-corecompletely drops dependencies on specific stack implementations (devflow-ext-rust,devflow-ext-node).Dynamic Boot Wiring: At boot,
devflow-clidynamically instantiates extensions and places them into anExtensionRegistry.Subprocess Delegation: For extensions not built into the CLI, Devflow will discover binaries in
$PATHprefixed withdevflow-ext-. It will probe these binaries by executing them with--discover, which returns a JSON array of supported capabilities.Execution Protocol: To execute a targeted command, the Core serialization engine pipes a standard JSON
CommandRefto the external binary via standard IOstdin(using--build-action). The binary returns anExecutionAction(program and arguments) as JSON overstdout.
Consequences¶
Positive¶
devflow-coreis purely an orchestration engine, completely uncoupled from language specifics.Teams can write new Devflow extensions in any language (Go, Python, Bash) simply by writing a binary that responds to
--discoverand--build-actionwith JSON.Command mapping logic natively resides inside the specific technology stack crate instead of sprawling match statements inside
devflow-cli/src/executor.rs.
Negative¶
Serialization overhead when passing Command contexts to sub-processes.
Reliance on
$PATHconfigurations means execution environments must be properly curated for subprocess discovery to succeed.