Skip to content

Design ACP propulsion layer for controller-driven sessions #23

@julianknutsen

Description

@julianknutsen

Problem

Gas City already has ACP transport support. We can:

  • start ACP-backed sessions
  • send prompts (Nudge)
  • wait for one in-flight prompt to finish (waitIdle)
  • capture recent output in a circular buffer for Peek

But we do not have the higher-level behavior the audit calls "ACP propulsion parity".

That phrase is opaque, so here is the practical meaning:

We are missing a controller-driven ACP workflow layer that can temporarily
"take the wheel" of an ACP session for bounded automated work, manage its
output/state cleanly, and then hand control back safely.

Current State

What ACP already does:

  • headless ACP session startup and handshake
  • prompt delivery to the session
  • busy tracking via an active prompt ID
  • recent output capture from session/update
  • Peek() over captured output

What ACP does not do yet:

  • explicit "session is being propelled" lifecycle state
  • output suppression / separation for controller-driven prompts
  • trigger detection for entering or leaving a propelled phase
  • larger / special-purpose buffering for those automated flows
  • structured event-driven handoff between propelled phases
  • safety rails and tests around this higher-level mode

Goal

Design and implement an ACP propulsion layer on top of the existing ACP runtime.

The goal is not "make ACP work" — ACP already works.

The goal is to make ACP good for controller-orchestrated automation, where
internal controller prompts should be:

  • bounded
  • stateful
  • less noisy than normal user-facing interaction
  • recoverable / testable
  • clearly separated from ordinary session activity

Why This Matters

ACP is the cleanest runtime surface for structured, headless orchestration.

Without a propulsion layer, controller automation over ACP is just "send a
prompt and hope the surrounding lifecycle works out". That is enough for basic
transport, but not for richer automated handoffs.

A propulsion layer would let the controller do things like:

  • enter a short automation phase
  • suppress or isolate controller-only chatter
  • watch for completion / trigger conditions
  • hand the session back to normal operation safely

Design Areas

1. Propulsion state model

  • What is the explicit runtime state for "being propelled"?
  • Is propulsion session-scoped, turn-scoped, or request-scoped?
  • How is propulsion state exposed to the controller/runtime layer?

2. Output handling

  • Should propelled output be hidden, tagged, or stored separately?
  • What output should still surface via Peek()?
  • Do we need a separate propulsion buffer or transcript channel?

3. Trigger / handoff model

  • What starts a propelled phase?
  • What ends it?
  • How does the controller detect completion vs stuck vs interrupted?
  • How do multi-phase handoffs work without losing ordering?

4. Safety and recovery

  • What happens if the ACP process exits mid-propulsion?
  • What happens on controller restart?
  • How do we avoid orphaned propelled state?
  • What is the timeout / cancellation contract?

5. Runtime contract surface

  • Do we need a first-class runtime capability for propulsion?
  • Is WaitForIdle / busy tracking sufficient, or do we need more explicit APIs?
  • How should propulsion interact with existing Nudge, Peek, and session metadata?

Non-Goals

  • Do not re-litigate whether ACP transport exists; it already does.
  • Do not require tmux-style terminal attach semantics for ACP.
  • Do not overfit this to a single Gastown prompt pattern if a smaller runtime contract is enough.

Minimum Acceptance Criteria

  • ACP-backed sessions can enter a bounded controller-driven propulsion phase.
  • Propelled work has an explicit lifecycle and completion contract.
  • Output behavior during propulsion is defined and tested.
  • Failure / restart behavior is defined and tested.
  • The design clearly explains when propulsion should be used versus plain ACP nudges.

Open Questions

  • Is propulsion primarily a runtime concern, a controller concern, or a joint contract?
  • Should propelled output be completely suppressed or just separated/annotated?
  • Do we need a dedicated propeller component, or just a stricter ACP request lifecycle?
  • What is the smallest useful version that gives real value without over-building?

Reference

  • docs/archive/analysis/gastown-upstream-audit.md
    Delta 4: ACP propulsion parity

Metadata

Metadata

Assignees

No one assigned

    Labels

    kind/designDesign / Product questions we need to resolvepriority/p3Backlog — good idea, reviewed when there's bandwidth

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions