Skip to content

Keep the Planner while its workflows run, with Stop/Resume and a run card - #230

Open
lavaman131 wants to merge 7 commits into
atomic-full-plannerfrom
atomic-planner-run-control
Open

lavaman131 wants to merge 7 commits into
atomic-full-plannerfrom
atomic-planner-run-control

Conversation

@lavaman131

Copy link
Copy Markdown
Collaborator

Stacked on #215. Partly implements #221.

An atomic Planner session that starts an Atomic workflow now outlives its turn. Until now, Chopin destroyed the session when the turn ended, which left the run orphaned seconds after launch.

What changes

  • The session stays while it owns runs. An atomic Planner session is kept, with its owner binding and the loaded document, as long as it has live or paused workflow runs. Chopin tracks those runs through Atomic's workflow activity stream. The next turn reuses the session, so the Planner can still steer its runs over Intercom. The session is released when its runs end, when the owner binding ends, or when the document closes.
  • Stop and Resume. Stop Planner pauses the session's live runs through the session's own workflow tool, which returns a structured result instead of a dropped UI notice. Atomic can't pause a run whose only live stage is waiting on a question, so that run is quit instead. It stays resumable and its open question is withdrawn from Decisions. The new chat:resume message and the Resume Planner button resume paused runs.
  • Run card in Chat. Each run gets a card showing its name, status (running, waiting on Decisions, paused, finished, blocked, failed, or stopped), elapsed time, and each stage with its status and duration. A pulsing dot marks live work and stays still under reduced motion. Ended runs collapse to one line with the stages behind a toggle, and the transcript records how each run ended. A design-audit specimen covers the running, waiting, paused, blocked and finished states.
  • create_document outcomes. It now reports title-taken, and declares its idempotency-conflict, document-unavailable and validation-issue outcomes in its output schema. Before, strict MCP clients rejected those responses as schema violations.
  • Working directory. Without a checkout, the Planner's working directory moves from the shared tmp directory to a per-channel directory under Chopin's per-user state directory.

Verification

  • bun test: 1755 pass, 2 PostgreSQL skips, 0 fail.
  • bun run types and bun run ci pass, with no new Impeccable findings.
  • Manual agent-browser run against a local server, with the full atomic Planner running a planning workflow on a private demo repository:
    • the run card tracked the stages;
    • Stop paused the run and Resume continued it;
    • two Decisions questions were answered in the browser;
    • the workflow wrote its formal specification and plan, and the document reached revision 12.

Known gaps

Assistant-workflow: inline
Assistant-verification: bun test passed: 1755 pass, 2 skip, 0 fail
Assistant-verification: bun run types and bun run ci passed
Assistant-verification: agent-browser E2E passed: run card, Stop/Resume, Decisions answered, workflow wrote its spec and plan
Co-authored-by: Alex Lavaee lavaman131@github.com

Chopin destroyed every Planner session when its turn ended. A workflow the
atomic Planner starts runs in the background under that session, so it
was orphaned seconds after launch and never progressed. Keep an atomic
Planner session, its owner binding, and the loaded document while the
session still owns live or paused workflow runs, tracked through Atomic's
workflow activity stream; the next turn reuses it so the Planner can still
steer its runs. The session is let go when the runs finish, the owner
binding ends, or the document closes.

Stop Planner now also pauses the session's live runs, resumably, and a
new Resume Planner control (`chat:resume`) resumes them. Chat state
carries the running and paused counts, and the composer shows them.
Run control goes through the session's own workflow commands until the
SDK exposes run-control primitives.

The document's working directory without a checkout moves from the shared
temporary directory to a per-channel directory under Chopin's per-user
state directory, so workflow files survive restarts.

Assistant-model: Claude Opus 5.5
Assistant-workflow: inline
Assistant-verification: bun test passed: 1751 pass, 2 PostgreSQL skips, 0 fail, including new retention, pause, resume, release, and run-classification tests
Assistant-verification: bun run types passed: all workspaces
Assistant-verification: bun run ci passed: dprint, oxlint, tokens, type scale, Impeccable (no new findings)
Assistant-verification: source check passed: DBOS records showed a Planner-launched run with no progress after its turn ended, matching the per-turn session disposal
User-preference: A pause in the Planner pauses its workflows and resume resumes everything; steering goes to the main chat, which decides whether to steer a workflow over intercom
User-preference: Keep long-lived Planner working directories out of the shared tmp
Co-authored-by: Alex Lavaee <lavaman131@github.com>
Document titles are unique per repository, so creating a second document
with an existing title failed in storage and came back as
idempotency-conflict, which reads as a reused key. Report it as
title-taken instead. create_document's output schema also described only
success, so strict MCP clients rejected its idempotency-conflict,
document-unavailable, and validation-issue responses as schema
violations and callers never saw the real outcome; declare them the way
update_document does.

Assistant-model: Claude Opus 5.5
Assistant-workflow: inline
Assistant-verification: bun test passed: 1752 pass, 2 PostgreSQL skips, 0 fail, including a new hosted test for title-taken
Assistant-verification: bun run types passed: all workspaces
Assistant-verification: bun run ci passed: dprint, oxlint, tokens, type scale, Impeccable (no new findings)
Assistant-verification: raw JSON-RPC probe passed: a fresh key with an existing title returned idempotency-conflict before this change, and a new title succeeded
Co-authored-by: Alex Lavaee <lavaman131@github.com>
… prompt

Replace the running/paused count with a card per run, built from Atomic's
workflow lifecycle hooks: the run's name and status (running, waiting on
Decisions, paused, or ended), elapsed time, each stage it reached with
its status and duration, and a link to the Decisions it waits on. Chat
records a line when a run ends. Stop now passes --yes to the pause
command: without it, Atomic asked the host to confirm, which Chopin
routes to Decisions, so the pause waited on a question instead of
pausing. A design-audit specimen covers the running, waiting, paused,
and finished states.

Assistant-model: Claude Opus 5.5
Assistant-workflow: inline
Assistant-verification: bun test passed: 1753 pass, 2 PostgreSQL skips, 0 fail, including run-card folding, paused/waiting/finished status, and the run-ended transcript line
Assistant-verification: bun run types passed: all workspaces
Assistant-verification: bun run ci passed: dprint, oxlint, tokens, type scale, Impeccable (no new findings)
Assistant-verification: agent-browser E2E failed before this change: Stop Planner on a run waiting in Decisions left "1 workflow running" because the pause waited on its own confirmation
User-preference: Show the workflow's current stages in Chopin, and have pause or quit change what Chat shows immediately
Co-authored-by: Alex Lavaee <lavaman131@github.com>
…se live runs

Stop Planner reported that it paused the workflows, but they kept
running: the /workflow slash command reports its outcome only through
ui.notify, which a headless session drops, so a refused or no-op pause
looked like success. Run pause and resume through the session's own
workflow tool with a real tool context instead, so the outcome returns
as a result and a failure reaches the chat transcript.

The run card's spinner never animated because chat-tool-loader has no
animation in the web app. Live runs and running stages now show a
pulsing dot that stays still under reduced motion.

Assistant-model: Claude Opus 5.5
Assistant-workflow: inline
Assistant-verification: bun test passed: 1754 pass, 2 PostgreSQL skips, 0 fail, including run control through the workflow tool and its failure path
Assistant-verification: bun run types passed: all workspaces
Assistant-verification: bun run ci passed: dprint, oxlint, tokens, type scale, Impeccable (no new findings)
Assistant-verification: agent-browser E2E failed before this change: Stop Planner posted "paused its workflows" while the run card stayed running and no pause was recorded
User-preference: Live workflow runs in Chopin show a pulsing dot rather than a spinner
Co-authored-by: Alex Lavaee <lavaman131@github.com>
Atomic pauses running and pending stages only, so Stop Planner on a run
whose live stage was waiting on a question changed nothing, while the
transcript said it paused. Read the workflow tool's reported status,
and when a pause changes nothing, quit each live run instead: quitting
keeps the run resumable, withdraws its open question from Decisions,
and asks it again on resume. A run that neither pause nor quit can stop
reports the failure in Chat.

Assistant-model: Claude Opus 5.5
Assistant-workflow: inline
Assistant-verification: bun test passed: 1755 pass, 2 PostgreSQL skips, 0 fail, including pause, quit fallback, and unstoppable-run failure
Assistant-verification: bun run types passed: all workspaces
Assistant-verification: bun run ci passed: dprint, oxlint, tokens, type scale, Impeccable (no new findings)
Assistant-verification: agent-browser E2E failed before this change: Stop Planner on a run waiting in Decisions left the run card running
User-preference: A pause in the Planner pauses its workflows and resume resumes everything
Co-authored-by: Alex Lavaee <lavaman131@github.com>
…ocked

A run card vanished the moment its last run ended, because Chat kept
cards only while a run was live or paused. Keep ended cards as a one-line
summary with the stage list behind a toggle. A run Atomic ends as
blocked, for example at its review limit, showed as failed; it now shows
as blocked, and the transcript line says it ended blocked.

Assistant-model: Claude Opus 5.5
Assistant-workflow: inline
Assistant-verification: bun test passed: 1755 pass, 2 PostgreSQL skips, 0 fail
Assistant-verification: bun run types passed: all workspaces
Assistant-verification: bun run ci passed: dprint, oxlint, tokens, type scale, Impeccable (no new findings)
Assistant-verification: agent-browser E2E failed before this change: a run blocked at its review limit disappeared from Chat and its transcript line said "failed after 31 min"
Co-authored-by: Alex Lavaee <lavaman131@github.com>
@lavaman131
lavaman131 added this pull request to stack #220 September 30, 2026 17:13
Upgrade the Atomic harness to 0.9.25-alpha.4, whose SDK exposes
session.workflows (bastani-inc/atomic#3377). Stop and Resume now call
session.workflows.pause({ all: true }) and resume each paused run, and a
partial pause reports the runs still active, replacing the workflow tool
called with a hand-built tool context and the quit fallback.

Atomic now counts a run whose stage waits on a question as paused and
leaves the question open, so Stop no longer withdraws it from Decisions.
An answer given while the run is paused is recorded but returned to the
run only after Resume, so the paused run never advances. A run with a
stage waiting on a question now shows as waiting on Decisions even when
no prompt lifecycle event arrives.

Assistant-model: Claude Opus 5.5
Assistant-workflow: inline
Assistant-verification: bun test passed: 1757 pass, 2 PostgreSQL skips, 0 fail, including run control, held answers for paused and child runs, and the waiting count
Assistant-verification: bun run types passed: all workspaces
Assistant-verification: bun run ci passed: dprint, oxlint, tokens, type scale, Impeccable (no new findings)
User-preference: Use Atomic's SDK run-control primitives instead of slash commands or tool workarounds
Co-authored-by: Alex Lavaee <lavaman131@github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant