Context
Per ADR-0030, rootless-podman OCI provisioning moves OUT of the msb backend adapter and INTO a neutral patterns kit (integrations/isolation/acq-kits/oci-engine/). The kit shipped in agentic-coding-patterns v1.10.0 (2dd2ad6ad5f63b842d732424bed5ba9aebeed676) and declares schemaVersion: "hybrid/v1", kind: mixin, name: oci-engine. This issue tracks the quickstart-side work to complete that migration.
Rewritten 2026-10-02. The original plan called for a bespoke ACQ_ENABLE_OCI_KIT environment gate. That design is superseded: #500 landed the generic opt-in kit catalog and acq configure, so oci-engine should be a catalog entry like any other kit — not a special case acq knows about by name. See "Superseded design" below for what NOT to build.
Blocked on / sequencing
Blocked on #474 merging. main currently pins
agentic-coding-patterns v1.9.0 (6c6753c60a2b24322fb2e8c0d8e8af60c56ede8f), whose
integrations/isolation/acq-kits/ contains only openchamber and paseo — there is no
oci-engine directory at that ref. The kit first appears in v1.10.0
(2dd2ad6ad5f63b842d732424bed5ba9aebeed676), and the pin bump to v1.10.0 lands in
#474.
This matters because _acq_apply_configured_extra_kits validates a configured kit name only
against the local ACQ_OPTIN_KIT_NAMES array; it does not verify the name resolves at the
pinned ref. So adding oci-engine to the catalog while the pin is still v1.9.0 would let
acq configure offer a kit whose ref points at a non-existent directory, and the adapter's
kit fetch (_acq_msb_fetch_kit) aborts the create with exit 1 rather than skipping it.
Trigger to start this work: #474 merges (carrying the
v1.10.0 pin). Do not add the catalog entry on a branch cut from a v1.9.0-pinned main, and do
not duplicate the pin bump here — it would conflict with #474.
Within this issue, keep step 1 (add the catalog entry) before step 2 (retire the adapter
auto-install) so there is never a window where neither path provides an OCI engine.
Current state
acq.backends/msb.sh auto-installs podman itself: _acq_msb_ensure_oci (≈200 lines) is called from acq_backend_provision, gated on ACQ_MSB_ENSURE_OCI, which defaults to on. _acq_msb_grant_oci_devs re-grants /dev/net/tun + /dev/fuse on provision AND on acq_backend_start (/dev is a devtmpfs re-created each boot).
sbx has no OCI path at all, so the two backends are asymmetric today: msb sandboxes get podman unasked, sbx sandboxes never do.
- The generic opt-in machinery now exists on
main (ADR-0031): ACQ_OPTIN_KIT_NAMES / ACQ_OPTIN_KIT_DESCS, _acq_optin_kit_ref, _acq_apply_configured_extra_kits (reads config.yaml extra_kits:), acq_configure, and create_time_kit_picker. Catalog selections flow through ACQ_EXTRA_KITS → _build_kit_list → acq_cli_kits_write, so they are durable across shells and re-applied on resume.
Work
1. Add oci-engine to the opt-in kit catalog
Append oci-engine to ACQ_OPTIN_KIT_NAMES and a matching one-line description to ACQ_OPTIN_KIT_DESCS in acq.backends/common.sh. That is the whole selection mechanism — no OCI-specific ref builder, readiness probe, cache, or env gate. The kit becomes selectable via a single keystroke in acq configure and in the create-time picker, and is persisted per-sandbox by the existing kit-record path.
Requires the built-in patterns pin to be at v1.10.0 or later, since _acq_optin_kit_ref builds refs from PATTERNS_KIT_REF and _acq_apply_configured_extra_kits fails closed on a kit name that does not resolve. The pin bump lands in #474.
Per the catalog-membership rule recorded in ADR-0031 (prime-agent is omitted because it is a skeleton at the current pin), a catalog entry must be functional at the pinned ref. oci-engine at v1.10.0 qualifies.
2. Retire the adapter's OCI auto-install (BREAKING)
Remove _acq_msb_ensure_oci, _acq_msb_grant_oci_devs, ACQ_MSB_ENSURE_OCI, ACQ_MSB_PODMAN_PKGS, and all call sites (provision, acq_backend_start, and the prereq/diagnostic paths that reference them). The kit performs install + device-grant declaratively, for both backends.
This is a breaking change and must be committed as such (feat!: or a BREAKING CHANGE: footer) with a release note: an OCI engine is no longer provisioned by default. Users who rely on docker run / docker compose inside a sandbox must opt into the oci-engine kit via acq configure (or ACQ_EXTRA_KITS / --kit).
Two behavioral notes that make the kit the better path, worth stating in the commit body:
- The kit's startup script is gated on podman being present and revokes a stale device grant when the engine is absent. The adapter's
_acq_msb_grant_oci_devs grants /dev/net/tun + /dev/fuse unconditionally, so retiring it narrows device exposure.
- The kit applies identically on sbx and msb, ending the current asymmetry.
Sequence step 2 after step 1 so there is never a window with neither path active.
3. Update scripts/verify-backends
_verify_oci_checks currently proves acq's auto-installed podman on msb. Repoint it at the kit path (provision with the oci-engine kit selected) and drop the ACQ_MSB_ENSURE_OCI skip branch once the auto-install is gone. The patterns kit's own scripts/verify already exercises the kit on msb via acq.
4. Docs
docs/BACKEND_GUIDE.md — remove the ACQ_MSB_ENSURE_OCI / ACQ_MSB_PODMAN_PKGS env rows and rewrite the "Running OCI images inside the sandbox (podman)" section around the opt-in kit.
docs/CONCEPTS.md — describe OCI as a catalog kit chosen through acq configure, not as an advanced env-var toggle.
- ADR-0020 (
msb oci engine via podman) — supersede it, or add a status note pointing at ADR-0030 and ADR-0031: the podman-over-dind and rootless decisions still hold, but the mechanism and the default both changed.
Verification
acq configure offers oci-engine; selecting it writes extra_kits: to config.yaml; a subsequent acq create applies the kit; acq start in a fresh shell still re-applies it (the round-trip through acq_cli_kits_write / acq_cli_kits_load).
- With the kit not selected, no podman is installed and no device grant occurs on either backend.
- With the kit selected on msb: rootless podman works,
docker resolves to podman, and /dev/net/tun + /dev/fuse are group-scoped to the agent after a stop/start cycle.
- The patterns kit's own
scripts/verify passes against a build of acq with the auto-install removed.
- Full offline suite green.
ACQ_BUILTIN_KIT_COUNT assertions should remain at 4 — a catalog kit lands after the built-in block and must not inflate the built-in count.
Superseded design — do NOT build this
The original version of this issue specified a bespoke ACQ_ENABLE_OCI_KIT env gate with a dedicated _acq_oci_engine_kit_ref, an acq_oci_engine_kit_ready validation probe, a readiness cache, a "kit not available, falling back to adapter" notice, and an adapter-side _oci_kit_selected suppression flag keyed on the exact OCI kit ref. That makes oci-engine a kit acq knows about by name, which is the opposite of the goal. The generic catalog supersedes it on every axis — discoverability, durability across shells, resume behavior, per-sandbox deviation, and lines of code in acq.
Refs
- ADR-0030 (agent kits on a devenv base) — the decision moving OCI provisioning into a kit
- ADR-0031 (interactive
acq configure) — the generic opt-in catalog this now rides on
- ADR-0020 (msb OCI engine via podman) — the adapter-era decision to supersede
- agentic-coding-patterns
integrations/isolation/acq-kits/oci-engine/ and its docs/decisions/
Context
Per ADR-0030, rootless-podman OCI provisioning moves OUT of the msb backend adapter and INTO a neutral patterns kit (
integrations/isolation/acq-kits/oci-engine/). The kit shipped in agentic-coding-patterns v1.10.0 (2dd2ad6ad5f63b842d732424bed5ba9aebeed676) and declaresschemaVersion: "hybrid/v1",kind: mixin,name: oci-engine. This issue tracks the quickstart-side work to complete that migration.Blocked on / sequencing
Blocked on #474 merging.
maincurrently pinsagentic-coding-patterns v1.9.0 (
6c6753c60a2b24322fb2e8c0d8e8af60c56ede8f), whoseintegrations/isolation/acq-kits/contains onlyopenchamberandpaseo— there is nooci-enginedirectory at that ref. The kit first appears in v1.10.0(
2dd2ad6ad5f63b842d732424bed5ba9aebeed676), and the pin bump to v1.10.0 lands in#474.
This matters because
_acq_apply_configured_extra_kitsvalidates a configured kit name onlyagainst the local
ACQ_OPTIN_KIT_NAMESarray; it does not verify the name resolves at thepinned ref. So adding
oci-engineto the catalog while the pin is still v1.9.0 would letacq configureoffer a kit whose ref points at a non-existent directory, and the adapter'skit fetch (
_acq_msb_fetch_kit) aborts the create withexit 1rather than skipping it.Trigger to start this work: #474 merges (carrying the
v1.10.0 pin). Do not add the catalog entry on a branch cut from a v1.9.0-pinned
main, and donot duplicate the pin bump here — it would conflict with #474.
Within this issue, keep step 1 (add the catalog entry) before step 2 (retire the adapter
auto-install) so there is never a window where neither path provides an OCI engine.
Current state
acq.backends/msb.shauto-installs podman itself:_acq_msb_ensure_oci(≈200 lines) is called fromacq_backend_provision, gated onACQ_MSB_ENSURE_OCI, which defaults to on._acq_msb_grant_oci_devsre-grants/dev/net/tun+/dev/fuseon provision AND onacq_backend_start(/devis a devtmpfs re-created each boot).sbxhas no OCI path at all, so the two backends are asymmetric today: msb sandboxes get podman unasked, sbx sandboxes never do.main(ADR-0031):ACQ_OPTIN_KIT_NAMES/ACQ_OPTIN_KIT_DESCS,_acq_optin_kit_ref,_acq_apply_configured_extra_kits(readsconfig.yamlextra_kits:),acq_configure, andcreate_time_kit_picker. Catalog selections flow throughACQ_EXTRA_KITS→_build_kit_list→acq_cli_kits_write, so they are durable across shells and re-applied on resume.Work
1. Add
oci-engineto the opt-in kit catalogAppend
oci-enginetoACQ_OPTIN_KIT_NAMESand a matching one-line description toACQ_OPTIN_KIT_DESCSinacq.backends/common.sh. That is the whole selection mechanism — no OCI-specific ref builder, readiness probe, cache, or env gate. The kit becomes selectable via a single keystroke inacq configureand in the create-time picker, and is persisted per-sandbox by the existing kit-record path.Requires the built-in patterns pin to be at v1.10.0 or later, since
_acq_optin_kit_refbuilds refs fromPATTERNS_KIT_REFand_acq_apply_configured_extra_kitsfails closed on a kit name that does not resolve. The pin bump lands in #474.Per the catalog-membership rule recorded in ADR-0031 (
prime-agentis omitted because it is a skeleton at the current pin), a catalog entry must be functional at the pinned ref.oci-engineat v1.10.0 qualifies.2. Retire the adapter's OCI auto-install (BREAKING)
Remove
_acq_msb_ensure_oci,_acq_msb_grant_oci_devs,ACQ_MSB_ENSURE_OCI,ACQ_MSB_PODMAN_PKGS, and all call sites (provision,acq_backend_start, and the prereq/diagnostic paths that reference them). The kit performs install + device-grant declaratively, for both backends.This is a breaking change and must be committed as such (
feat!:or aBREAKING CHANGE:footer) with a release note: an OCI engine is no longer provisioned by default. Users who rely ondocker run/docker composeinside a sandbox must opt into theoci-enginekit viaacq configure(orACQ_EXTRA_KITS/--kit).Two behavioral notes that make the kit the better path, worth stating in the commit body:
_acq_msb_grant_oci_devsgrants/dev/net/tun+/dev/fuseunconditionally, so retiring it narrows device exposure.Sequence step 2 after step 1 so there is never a window with neither path active.
3. Update
scripts/verify-backends_verify_oci_checkscurrently proves acq's auto-installed podman on msb. Repoint it at the kit path (provision with theoci-enginekit selected) and drop theACQ_MSB_ENSURE_OCIskip branch once the auto-install is gone. The patterns kit's ownscripts/verifyalready exercises the kit on msb via acq.4. Docs
docs/BACKEND_GUIDE.md— remove theACQ_MSB_ENSURE_OCI/ACQ_MSB_PODMAN_PKGSenv rows and rewrite the "Running OCI images inside the sandbox (podman)" section around the opt-in kit.docs/CONCEPTS.md— describe OCI as a catalog kit chosen throughacq configure, not as an advanced env-var toggle.msb oci engine via podman) — supersede it, or add a status note pointing at ADR-0030 and ADR-0031: the podman-over-dind and rootless decisions still hold, but the mechanism and the default both changed.Verification
acq configureoffersoci-engine; selecting it writesextra_kits:toconfig.yaml; a subsequentacq createapplies the kit;acq startin a fresh shell still re-applies it (the round-trip throughacq_cli_kits_write/acq_cli_kits_load).dockerresolves to podman, and/dev/net/tun+/dev/fuseare group-scoped to the agent after a stop/start cycle.scripts/verifypasses against a build of acq with the auto-install removed.ACQ_BUILTIN_KIT_COUNTassertions should remain at 4 — a catalog kit lands after the built-in block and must not inflate the built-in count.Superseded design — do NOT build this
The original version of this issue specified a bespoke
ACQ_ENABLE_OCI_KITenv gate with a dedicated_acq_oci_engine_kit_ref, anacq_oci_engine_kit_readyvalidation probe, a readiness cache, a "kit not available, falling back to adapter" notice, and an adapter-side_oci_kit_selectedsuppression flag keyed on the exact OCI kit ref. That makesoci-enginea kit acq knows about by name, which is the opposite of the goal. The generic catalog supersedes it on every axis — discoverability, durability across shells, resume behavior, per-sandbox deviation, and lines of code in acq.Refs
acq configure) — the generic opt-in catalog this now rides onintegrations/isolation/acq-kits/oci-engine/and itsdocs/decisions/