Skip to content

Deliver spawned-task settle outcomes back to the launching run#348

Open
daniel-lxs wants to merge 2 commits into
developfrom
feat/verification-task-feedback
Open

Deliver spawned-task settle outcomes back to the launching run#348
daniel-lxs wants to merge 2 commits into
developfrom
feat/verification-task-feedback

Conversation

@daniel-lxs

Copy link
Copy Markdown
Member

Problem

The environment-setup workflow launches a verification task against the persisted environment — the end-to-end test of the product pipeline: Roomote provisioning a fresh workspace from the config, executing the setup commands the way the platform executes them, and an agent working inside the result. That test stays (rework of the reverted #340, per the Slack discussion).

What was broken is how its outcome got consumed: the setup agent waited by polling get_summary, and that wait is purely agent-dependent. If the setup task went idle while the verification task ran, nothing woke it when the child settled — the verification ran, but its verdict was lost and the environment could be handed over on local evidence alone.

Changes

Deterministic feedback (platform-side, no agent diligence required)

  • manage_tasks launch gains notifyOnSettle. On run-token standard launches it stamps sourceRunId with the launching run and persists notifySourceRunOnSettle on the spawned task's payload. User-token launches ignore the flag (no run to notify).
  • finishRun now calls a new notifySourceRunOnSettle: when an opted-in run settles (completed / failed / canceled / idle), the platform injects a Spawned task update prompt into the launching run's sandbox via the existing sandbox RPC — waking the parent if it went idle — carrying the settle status, environmentSetupState, and any error, plus a pointer to get_summary / get_messages for the full outcome. Same inject-on-settle pattern Make environment setup completion observable to the task and platform #333 established for background setup, one level up.
  • Safety properties: at-most-once delivery (guarded via the run's result JSON, so an idle-then-completed run doesn't notify twice), same-task resume chains excluded (sourceRunId is shared with resume lineage), exited/sandbox-less parents skipped, deployment-service-principal token so the parent's acting user is untouched, and the whole path never throws out of finishRun. Delivery and failures are recorded as run lifecycle events.

Skill (prompt-first)

  • The verification launch sets notifyOnSettle: true; a new step tells the setup agent the settle message is the primary completion signal — it can safely go idle between checks — with get_summary polling as the fallback. The fix loop relaunches with the flag and waits for the new notification.
  • The verification task's prompt reads .roomote/setup-status.json first, waits for a terminal state before judging, and reports failing command names/exit codes/log excerpts.

Re-lands the ground truth from #340 (reverted in #346)

  • environmentSetupState in the task summary API and the Environment Setup: line in get_summary, so both the settle notification and the fallback polling carry deterministic setup evidence.

Not included (deliberately): the in-workspace proof-runner verification loop from #340 — orthogonal to this fix and can be discussed separately.

Testing

  • SDK: 8 new notifySourceRunOnSettle tests (delivery + prompt contents, failed-run evidence, opt-in/pointer/idempotence/resume-chain/exited-parent guards, never-throws) and the finish-run suite passes with the notifier mocked (50).
  • API: 3 new launchTask tests (run-token stamping, user-token ignore, no-flag default) plus the re-landed summary assertion (14 total).
  • Worker: re-landed get_summary rendering tests (10).
  • Skill: assertions for the notifyOnSettle launch, settle-notification steps, and ground-truth wording; full cloud-agents suite passes (475).
  • Typecheck clean across types, sdk, api, worker, cloud-agents, web; changed files pass Prettier.

🤖 Generated with Claude Code

The environment-setup workflow's spawned verification task is the end-to-
end test of the product pipeline (fresh provisioning, platform-executed
setup commands, an agent working in the environment), but consuming its
outcome depended on the setup agent's polling discipline: an idle parent
never woke when the verification task settled, so the verdict was lost.

Make the wait deterministic:

- manage_tasks launch gains notifyOnSettle. On run-token standard
  launches it stamps sourceRunId with the launching run and persists
  notifySourceRunOnSettle on the spawned task payload.
- finishRun now calls notifySourceRunOnSettle: when an opted-in run
  settles (completed / failed / canceled / idle), the platform injects a
  "Spawned task update" prompt into the launching run's sandbox — waking
  it if idle — with the settle status, environmentSetupState, and error.
  Delivery is at-most-once (guarded via the run result JSON), skips
  same-task resume chains and exited parents, uses a deployment-service-
  principal token so the parent's acting user is untouched, and never
  throws; delivery and failures are recorded as run lifecycle events.
- The environment-setup skill launches verification with notifyOnSettle,
  treats the settle message as the primary completion signal with
  get_summary polling as fallback, and its verification prompt reads
  .roomote/setup-status.json before judging.
- Re-lands the #340 ground truth reverted in #346: environmentSetupState
  in the task summary API and the Environment Setup line in get_summary.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@roomote-roomote

roomote-roomote Bot commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

No code issues found. See task

  • packages/cloud-agents/src/server/task-run-queue.ts:1409 Persisted the launching run ID on the fresh task_runs row, so standard child runs now retain sourceRunId for settle notifications.
  • packages/sdk/src/server/lib/task-runs/finish-run.ts:235-238 Passes the finalized sanitized error to the notifier instead of relying only on the pre-transaction run object.
  • packages/sdk/src/server/lib/task-runs/notify-source-run-on-settle.ts:121-136 Claims notification delivery with a conditional JSONB update before sending, preventing concurrent finalizations from sending duplicate prompts.

Reviewed 7b6d35c

- Persist sourceRunId on the fresh task_runs row: enqueueFreshLaunch
  dropped the task-level pointer, so every spawned run had a null
  sourceRunId and the settle notification could never fire.
- Splice the finalized error into the run passed to the notifier; the
  pre-transaction row still carried the previous error.
- Claim delivery atomically (conditional JSONB update on the marker)
  before sending, so concurrent finalizations cannot both notify.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.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