Skip to content

Add trigger-based prompt dispatch for Codex threads #83

@gaelic-ghost

Description

@gaelic-ghost

Summary

Add a SwiftASB-owned way to schedule or dispatch a prompt to a Codex thread when a defined trigger fires. Initial trigger candidates include GitHub release events, Codex lifecycle hooks such as a turn-completion Stop hook, and local app events from a SwiftUI host.

The core feature should be trigger-driven thread dispatch rather than a GitHub-specific integration: a source event selects a target thread strategy, renders a prompt from trusted metadata plus clearly marked untrusted event content, and starts a turn on an existing or newly created Codex thread.

Motivation

SwiftASB already exposes the important app-server primitives:

  • start a new thread
  • resume or reopen a stored thread
  • start a text turn on a thread
  • observe thread and turn state

That makes it a natural host-side foundation for automation like:

  • "When dependency repo X publishes a new release, ask Codex to inspect whether this project is affected."
  • "When one Codex thread finishes a turn, queue a follow-up prompt in another known thread."
  • "When a maintenance thread completes, ask a planning thread to summarize what should happen next."
  • "When a host app receives a local event, dispatch a prompt into a specific work thread."

There is also a useful short-term bridge: a triggering thread could sometimes queue a follow-up prompt into another arbitrary thread, rather than forcing every automation through a separate daemon or webhook listener.

Proposed Shape

Introduce a small dispatch model that can be used by host apps, hooks, or future trigger adapters:

struct CodexPromptDispatch {
    let source: CodexDispatchSource
    let target: CodexDispatchTarget
    let prompt: CodexDispatchPrompt
    let idempotencyKey: String
}

enum CodexDispatchSource {
    case githubRelease(repository: String, tag: String)
    case codexTurnCompleted(threadID: String, turnID: String)
    case localEvent(name: String, payload: JSONValue)
}

enum CodexDispatchTarget {
    case newThread(ThreadStartRequest)
    case existingThread(threadID: String)
    case latestMatching(ThreadListQueryDescriptor)
}

This is illustrative, not final API. The important boundary is that the dispatch system owns trigger metadata, target-thread selection, prompt rendering, and duplicate prevention, while the existing thread APIs continue to own thread creation and turn start behavior.

Hook-Backed Option

Codex Hooks may be a good first trigger source for thread-to-thread follow-ups. A Stop hook could call a small dispatcher process, and that dispatcher could use SwiftASB to target another thread.

This should stay explicit and opt-in. Hook-backed dispatch needs guardrails so a completion-triggered dispatch cannot recursively create unbounded turns.

GitHub Release Option

GitHub release triggers could be fed into the same dispatch model through one of several adapters:

  • a local webhook receiver
  • a GitHub Action on a self-hosted Mac runner
  • a polling service that checks releases or tags
  • a manual host-app action that wraps release metadata into a dispatch source

GitHub-hosted Actions can detect release events, but local Codex access requires a deliberate bridge to the machine running Codex and SwiftASB.

Safety And Design Notes

  • Add idempotency so the same release, hook event, or local event does not dispatch repeatedly.
  • Mark external release notes, issue text, PR text, and changelogs as untrusted input inside rendered prompts.
  • Add loop prevention for hook-triggered dispatch, including an automation marker and a maximum dispatch depth.
  • Keep target-thread selection deterministic and inspectable.
  • Prefer descriptive failure messages that name the trigger source, target strategy, and most likely cause.
  • Avoid baking GitHub-specific behavior into the core thread API; GitHub should be an adapter over a general dispatch model.

Acceptance Criteria

  • A host app can ask SwiftASB to dispatch a text prompt to an existing thread by ID.
  • A host app can ask SwiftASB to create a new thread and immediately start a text turn from the same dispatch request.
  • Dispatch requests support an idempotency key or equivalent duplicate-prevention record.
  • Dispatch failures report the trigger source, target strategy, and failed operation.
  • Hook-triggered dispatch has explicit loop-prevention behavior documented and covered by tests.
  • GitHub release metadata can be represented as a dispatch source without requiring GitHub-specific public thread APIs.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions