Skip to content

feat(graph): run ADC's pr-review-with-approval workflow on the engine - #1011

Merged
drewstone merged 2 commits into
mainfrom
spike/adc-workflow-on-engine
Aug 24, 2026
Merged

feat(graph): run ADC's pr-review-with-approval workflow on the engine#1011
drewstone merged 2 commits into
mainfrom
spike/adc-workflow-on-engine

Conversation

@drewstone

Copy link
Copy Markdown
Contributor

What this is

The ADC integration spike the graph-engine map (#966) was built toward: agent-dev-container's real pr-review-with-approval template (workflow-templates.ts), hand-lowered to an EngineGraphSpec and run on the engine. ADC keeps its front-end and business kinds; the engine provides execution, durability, and the conserved pool.

Proof (all in tests/graph/adc-workflow-spike.test.ts, 5/5 green)

  • Approve path: the human wake releases the guarded edge; the review posts exactly once with the exact args the template's ${...} expressions assemble.
  • Timeout path: offline, onTimeout: default resolves through the suspension's onExpire: 'default'; the post is skipped and the run completes cleanly.
  • Kill-anywhere over HOST kinds: killed at EVERY journal boundary (~50) and restarted — a settled agent run never re-executes, a posted review never re-posts, bytes identical to the uninterrupted run.
  • Budget: ADC's maxRunCostUsd maps to Budget.maxUsd; a pool smaller than the agent's spend fails the run.
  • UI shape: engine settles project onto the actionResults rows the run-detail UI reads (succeeded/skipped/waiting, per-step cost).

Two kernel defects the spike exposed (first commit)

  1. Resume leaked dead inline reservations. A spawned-never-settled child kept its budget reservation across restart. For an inline runtime the process death proves the child dead; holding the reservation starved the pool and refused the next metered node (budget-exhausted, run ends unreachable-terminal). The existing replay test never saw it — its chain is all-pure, so reservations were zero. uncertainSpawnBudgets now charges only runtimes that can re-attach (bridge, sandbox).
  2. A parked waitForWakes run ignored abort. Nothing connected the abort signal to the wake wait, so a suspended run could never be shut down. The wait now races the abort.

Integration findings for the ADC lift (no code needed now)

  • Suspension tokens are per-VISIT. A crash before the park is durable re-enters the node and re-mints. A host must bind asks to the token read from the journaled waiting event (ADC's decision row already works this way), never precompute one.
  • The run handle has no "parked" signal — the host observes the durable waiting event, which matches ADC's transports acting on the decision row.
  • External effects are at-least-once across a crash (kill between the provider call and its settle re-invokes, by onCrash: 'restart' declaration). Exactly-once delivery needs an idempotency key at the hub-executor seam; the engine's stable instance identity supplies it. The fake host models this.
  • Multi-source ${...} templates lower to pure script nodes; single-field reads are edge projections; ADC's if: guards are the engine's condition tree verbatim (it was adopted from ADC).

Verification

vitest run tests/graph/adc-workflow-spike.test.ts 5/5. Typecheck + lint green. Full local suite: graph/kernel/supervise all pass; the improvement/worktree files show the documented macOS baseline noise — the same files run in isolation fail identically (2) on this branch and on pristine origin/main, so the branch adds zero failures. Linux CI is the authority.

https://claude.ai/code/session_01CBYrFq6uXPbDwchUhRnVfT

…ort reach a parked run

A resumed run held the budget reservation of every spawned child that
never settled.
An inline executor runs inside the process that spawned it, so a resume
can prove it dead.
The held reservation starved the pool and refused the next metered node.
uncertainSpawnBudgets now keeps only runtimes that can re-attach.

A parked waitForWakes run also ignored the abort signal.
The wait now races the abort, so a host can shut a suspended run down.
… engine

Lower the real template to an EngineGraphSpec with two host kinds.
agent.run is metered into the conserved pool.
decision parks the run; the human answer arrives as a resume.
The if guard becomes the edge guard on the decision's data edge.

The spike proves: approve and timeout paths, the park across a process
restart, kill-anywhere replay at every journal boundary over host kinds,
the pool cap acting as maxRunCostUsd, and the settles projected onto the
actionResults shape the ADC run detail UI reads.
An external effect is at-least-once across a crash; the fake host models
the idempotency key that makes delivery exactly-once.

@tangletools tangletools left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Automated approval: author drewstone, all checks green.

@drewstone
drewstone merged commit 0cdf9fc into main Aug 24, 2026
4 checks passed
@drewstone
drewstone deleted the spike/adc-workflow-on-engine branch August 24, 2026 09:44
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.

2 participants