Skip to content

acq: make oci-engine an opt-in catalog kit and retire the adapter OCI auto-install #505

Closed

Description

@mogul

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/

Activity

  1. added
    enhancementNew feature or request
    maintenanceissues for attention to maintenance rotation
    on Oct 1, 2026
  2. added theissue type on Oct 1, 2026
  3. changed the title [-]acq(msb): wire the opt-in oci-engine kit and retire the adapter's OCI auto-install (ADR-0030)[/-] [+]acq: make oci-engine an opt-in catalog kit and retire the adapter OCI auto-install[/+] on Oct 2, 2026
  4. mogul commented on Oct 2, 2026

    @mogul
    ContributorAuthor

    Added a Blocked on / sequencing section: this work cannot start until #474 merges.

    Measured reason — main pins patterns v1.9.0 (6c6753c), and oci-engine does not exist at that ref:

    $ git ls-tree --name-only 6c6753c integrations/isolation/acq-kits/ | grep -E 'oci|openchamber|paseo'
    integrations/isolation/acq-kits/openchamber
    integrations/isolation/acq-kits/paseo
    
    $ git ls-tree --name-only v1.10.0 integrations/isolation/acq-kits/ | grep -E 'oci|openchamber|paseo'
    integrations/isolation/acq-kits/oci-engine
    integrations/isolation/acq-kits/openchamber
    integrations/isolation/acq-kits/paseo
    

    _acq_apply_configured_extra_kits validates a configured kit name only against the local ACQ_OPTIN_KIT_NAMES array — it does not check that the name resolves at the pinned ref. So adding the catalog entry on a v1.9.0-pinned main would let acq configure offer a kit whose ref points at a non-existent directory, and _acq_msb_fetch_kit aborts the create with exit 1 rather than skipping it.

    The v1.10.0 pin bump lands in #474, so that PR is the unblock trigger. Do not duplicate the pin bump here.

    AI-assisted (OpenCode).

  5. basiliskus commented on Oct 3, 2026

    @basiliskus
    Contributor

    Note while reviewing #474: the whitespace-normalization bug moved here

    Recording this against step 2 so it is not lost if the retirement slips. No action needed if step 2 lands as written — the parser below is inside the code this issue deletes, so fixing it separately would be wasted work.

    While reviewing #474 I found that ACQ_ENABLE_OCI_KIT enabled the kit on whitespace-padded off values, because the parser lowercased without trimming and treated everything outside an exact off-list as on. 4721aff resolved that by deleting the bespoke gate entirely (the right fix). But the identical parser still exists for the adapter toggle this issue retires, at acq.backends/msb.sh:584-588:

    ACQ_MSB_ENSURE_OCI="${ACQ_MSB_ENSURE_OCI-1}"
    case "$(printf '%s' "$ACQ_MSB_ENSURE_OCI" | tr '[:upper:]' '[:lower:]')" in
      ""|0|false|no|off) ACQ_MSB_ENSURE_OCI="" ;;
      *)                 ACQ_MSB_ENSURE_OCI="1" ;;
    esac

    Measured:

    ACQ_MSB_ENSURE_OCI=[0]        -> SKIP-OCI
    ACQ_MSB_ENSURE_OCI=[off]      -> SKIP-OCI
    ACQ_MSB_ENSURE_OCI=[OFF]      -> SKIP-OCI
    ACQ_MSB_ENSURE_OCI=[no]       -> SKIP-OCI
    ACQ_MSB_ENSURE_OCI=[0 ]       -> INSTALL-OCI     <- trailing space
    ACQ_MSB_ENSURE_OCI=[ false ]  -> INSTALL-OCI
    

    The difference from the ACQ_ENABLE_OCI_KIT case is the default. This one defaults to 1, so it is an opt-out: a padded value preserves the default rather than flipping behaviour, which is milder. But the thing it fails to disable is a provisioning step that installs packages and grants /dev/net/tun + /dev/fuse, so a user who believes they opted out of podman still gets it — and per this issue's own note, the adapter grants those devices unconditionally where the kit gates on podman being present.

    Pre-existing, not introduced by #474: the block is unchanged at that PR's merge-base (410f332), and #474's diff does not touch it. I did not raise it as a finding there for that reason.

    Two paths from here, whichever suits the sequencing:

    • Preferred: step 2 removes ACQ_MSB_ENSURE_OCI outright, and this note becomes moot. Nothing to do.
    • If step 2 slips past the next release, a one-line trim in the pipeline (tr -d '[:space:]' after the lowercase, or an explicit on-list) closes it in the meantime.

    Worth noting the same shape may exist on other toggles normalized this way — ACQ_MSB_PODMAN_PKGS is a value not a boolean, but it would be worth a grep for the ""|0|false|no|off) idiom elsewhere when this is picked up, rather than fixing one instance.

    Context: #474 is approved and the oci-engine kit is not in ACQ_OPTIN_KIT_NAMES yet (openchamber paseo at 5b2404a), so after that merges the adapter auto-install remains the only route to OCI. That is the window this issue closes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestmaintenanceissues for attention to maintenance rotation

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions