Summary
Adopt the SDK component-lifetime contract from bomly-dev/bomly-sdk#26 across CLI registration and managed-plugin pooling so embedded and managed modules have equivalent teardown behavior.
Current behavior
Embedded and managed resources are owned by unrelated paths:
internal/registry/module.go:RegisterModule validates a module and constructs every embedded component with context.Background().
internal/registry/builder.go invokes that registration while building the registry, without a component cleanup handle.
internal/plugin/pool.go:ClientPool owns one managed subprocess per plugin for the command and restarts a dead process at most once.
ClientPool.Shutdown closes clients but cannot report teardown errors.
internal/plugin/runtime/hashicorp/runtime.go:Client.Close calls Kill; there is no graceful component cleanup handshake.
As a result, an embedded constructor cannot observe command cancellation or register teardown, while a managed component is cleaned up only as a side effect of process termination.
Dependency
Blocked on the released SDK contract in bomly-dev/bomly-sdk#26. Use a local go.work only during cross-repository development; do not commit a replace directive. The final CLI change must pin an SDK tag.
Required behavior
- Propagate the command/component lifetime context into embedded module construction instead of creating a background context.
- Retain the SDK cleanup scope for as long as the registry/component is usable, then close it exactly once.
- Integrate managed subprocess shutdown with the same ownership model.
- If the SDK adds an optional graceful shutdown RPC, call it with a bounded timeout and fall back to the existing hard process termination when an old plugin returns
Unimplemented, the subprocess is already dead, or the grace period expires.
- Run every registered cleanup even when earlier cleanup fails; retain actionable plugin/component identity in joined errors.
- Preserve the existing one-restart bound and do not turn the command-scoped pool into a daemon.
Acceptance criteria
Architecture and compatibility
Record or extend the SDK lifecycle ADR under dev-docs/adr/ before merging. This issue must not change the bomly.plugin.v1 contract independently; additive wire work belongs in the SDK issue. Unimplemented is a compatibility result, not a plugin failure.
Out of scope
- Persistent agents, daemon process reuse, hot reload, or reactive reconfiguration.
- Raising the restart limit.
- Sandboxing native plugins.
Verification
Run:
make test
make build-lite
If the SDK pin or generated component data changes, also run make generate and commit the generated drift.
Summary
Adopt the SDK component-lifetime contract from bomly-dev/bomly-sdk#26 across CLI registration and managed-plugin pooling so embedded and managed modules have equivalent teardown behavior.
Current behavior
Embedded and managed resources are owned by unrelated paths:
internal/registry/module.go:RegisterModulevalidates a module and constructs every embedded component withcontext.Background().internal/registry/builder.goinvokes that registration while building the registry, without a component cleanup handle.internal/plugin/pool.go:ClientPoolowns one managed subprocess per plugin for the command and restarts a dead process at most once.ClientPool.Shutdowncloses clients but cannot report teardown errors.internal/plugin/runtime/hashicorp/runtime.go:Client.ClosecallsKill; there is no graceful component cleanup handshake.As a result, an embedded constructor cannot observe command cancellation or register teardown, while a managed component is cleaned up only as a side effect of process termination.
Dependency
Blocked on the released SDK contract in bomly-dev/bomly-sdk#26. Use a local
go.workonly during cross-repository development; do not commit areplacedirective. The final CLI change must pin an SDK tag.Required behavior
Unimplemented, the subprocess is already dead, or the grace period expires.Acceptance criteria
go.modcontains noreplace.Architecture and compatibility
Record or extend the SDK lifecycle ADR under
dev-docs/adr/before merging. This issue must not change thebomly.plugin.v1contract independently; additive wire work belongs in the SDK issue.Unimplementedis a compatibility result, not a plugin failure.Out of scope
Verification
Run:
make test make build-liteIf the SDK pin or generated component data changes, also run
make generateand commit the generated drift.