Skip to content

feat(workflow): run and resume workflows from the CLI - #97

Merged
Waishnav merged 70 commits into
pr/dw-3-enginefrom
pr/dw-4-cli-worker
Jul 27, 2026
Merged

feat(workflow): run and resume workflows from the CLI#97
Waishnav merged 70 commits into
pr/dw-3-enginefrom
pr/dw-4-cli-worker

Conversation

@Waishnav

@Waishnav Waishnav commented Jul 21, 2026

Copy link
Copy Markdown
Owner

The engine from #96 was only an in-process API. Users still needed a durable way to resolve scripts, launch runs independently of the initiating shell, inspect or cancel them later, isolate agent changes, resume prior work, and request structured output.

Add named and file-based script resolution, per-call workflow worktrees, the initial replay implementation, and JSON Schema enforcement for agent() results. A detached CLI worker now owns run execution and heartbeat state, while workflow run, status, cancel, and ls provide the first user-facing lifecycle controls.

Stack

Based on #96 and merged into #94 before the MCP and skill integration in #98.

Waishnav and others added 5 commits July 21, 2026 17:26
Named/file script resolve, agent worktree factory, resume matcher
(index+key then consume-once), and Ajv schema enforcement wired into
agent(). Adds ajv dependency.

Co-Authored-By: Claude <noreply@anthropic.com>
Detached __worker with heartbeat/cancel, real adapters via
runLocalAgentProvider, worktree isolation, and resume wiring.
setScriptPath persists script after run create.

Co-Authored-By: Claude <noreply@anthropic.com>
Always include bundled skills root when subagents enabled so seeding
subagent-delegation no longer hides later skills. Seed dynamic-workflows
alongside subagent-delegation on init.

Co-Authored-By: Claude <noreply@anthropic.com>
Load ordered enable-list from config/env, probe available providers on
init and doctor, and filter workflow CLI providers by enabled∩live.

Co-Authored-By: Claude <noreply@anthropic.com>
Gate on config.subagents. run_workflow spawns the same detached worker
as CLI; status long-polls journal events; cancel requests cooperative stop.

Co-Authored-By: Claude <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jul 21, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 0d3c0eb5-ccfa-4432-8970-e6834e11b050

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch pr/dw-4-cli-worker

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Comment thread src/workflow-cli.ts Outdated
});

const persisted =
priorScriptPath ??

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P0] Resume reuses the prior mutable script path and does not verify that the new run is in the same repository/workspace/base SHA. This can replay repository A in B, and prior.scriptHash can disagree with edited bytes executed later. Snapshot the exact validated source under the new run ID and require a matching repository identity/base revision (or an explicit override) before replay.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Partially addressed by stacked PR #108 (c8f0b65). Resume now reads the selected source, recomputes its hash, persists a fresh per-run script snapshot, updates the new run to that snapshot path, and the worker executes those exact bytes. That fixes the mutable prior-path / stale scriptHash half of this finding. The repository identity half is still open: resume does not require matching workspaceId/workspaceRoot/baseSha, so cross-workspace replay is still possible. Keeping this thread unresolved for that remaining check.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The mutable-source/hash half was addressed in #108, and PR #116 completes the replay contract with exact return-value persistence plus deterministic same-index prefix reuse. Mandatory workspace/repository identity matching is intentionally not added: runId and resume are designed to remain usable from Cursor, Pi, OpenCode, CLI, and other harnesses that do not own a DevSpace workspace ID. Project-local workflow path confinement is handled separately in the next follow-up rather than through workspace-ID authorization.

Comment thread src/workflow-cli.ts Outdated
console.log(formatRunLine(run));
if (run.pid && (run.status === "running" || run.status === "starting")) {
try {
process.kill(run.pid, "SIGTERM");

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P0] Sending SIGTERM immediately after setting the cooperative flag usually kills the worker before it can observe cancellation, clean up worktrees, or write terminal events. Please centralize CLI/MCP cancellation in a supervisor: request cancel, wait a grace period, then use the cross-platform terminateProcessTree fallback and atomically mark the run cancelled. The supervisor should also schedule reapStale().

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed by follow-up PR #115 (15be40e, 5a7a3db). CLI cancellation now uses the shared lifecycle supervisor: set the cooperative flag, wait a grace period, terminate the detached process tree through the cross-platform helper, escalate to SIGKILL when necessary, and atomically mark the run cancelled as a fallback. The server also schedules stale-worker reaping.

Comment thread src/workflow-cli.ts Outdated
}
}

store.completeRun(runId, { resultJson });

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P1] The run becomes completed before run_completed is appended. A status poll can observe terminal state and stop before the terminal event exists. Please update terminal status and append the corresponding terminal event in one SQLite transaction; use the same path for failed and cancelled runs.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed by follow-up PR #115 (dfbf5a1). Completed, failed, and cancelled transitions now update the run row and append the matching terminal event inside one immediate SQLite transaction. Pollers can no longer observe terminal status before its terminal event exists.

Comment thread src/workflow-schema.ts Outdated
Comment thread src/workflow-files.test.ts Outdated
Comment thread src/workflow-replay.ts Outdated
function toHit(call: WorkflowAgentCallRecord): WorkflowReplayHit {
if (call.structuredJson) {
try {
return {

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P0] Replay restores only the previous return value; it does not recreate filesystem side effects or reconnect the preserved worktree. A cached mutating agent can report success while the new run contains none of its changes. Please make mutating calls non-cacheable by default, or persist/apply a patch or resume the exact worktree as part of the replay contract.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed by follow-up PR #116 (57229cb, d12fc43). Resume now reuses only the longest unchanged same-index call prefix. The first mismatch closes replay for every later call. Worktree-isolated calls are explicitly non-replayable until DevSpace can restore their exact worktree, so a cached success can no longer stand in for absent worktree changes. Shared-checkout calls retain Claude Code-like prefix behavior and assume their filesystem effects remain in the checkout.

Waishnav and others added 18 commits July 21, 2026 22:55
Wire LocalAgentRunInput.schema through CodexSdkLocalAgentRuntime to
thread.run turn options, and surface parsed structured output.
Pass JSON Schema via outputFormat on query options and prefer
structured_output from result messages. OpenCode stays prompt-path only.
Hardcode NATIVE_SCHEMA_PROVIDERS; attempt 0 uses adapter schema without
prompt bloat, then prompt-repair retries with Ajv. Wire schema through
runProvider / CLI worker. Document in skill.
Waishnav added 25 commits July 27, 2026 13:01
refactor(agents): unify provider resolution and subagent guidance
feat(workflow): support agent profiles and project workflows
fix(workflow): replay deterministic call prefixes
fix(workflow): supervise cancellation and terminal lifecycle
feat(workflow): isolate workflow script execution
feat(ui): live workspace and workflow dashboards
feat(workflow): read-only project workflow TUI
feat(workflow): script iteration, replay provenance, and call inspection
refactor(workflow): model operational failures with better-result
refactor(workflow): strengthen contracts and zod boundaries
feat(agents): native schema for codex/claude agent({ schema })
feat(workflow): MCP tools, skill, agentProviders
@Waishnav
Waishnav marked this pull request as ready for review July 27, 2026 15:05
@Waishnav
Waishnav merged commit a28337e into pr/dw-3-engine Jul 27, 2026
3 checks passed
@Waishnav Waishnav changed the title feat(workflow): CLI worker, worktrees, resume, schema feat(workflow): run and resume workflows from the CLI Jul 30, 2026
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