Skip to content

fix(verify): coupled child state in predicates; child usage to the root - #225

Merged
davidkpiano merged 1 commit into
nextfrom
coupled-child-proofs
Nov 7, 2026
Merged

davidkpiano merged 1 commit into
nextfrom
coupled-child-proofs

Conversation

@davidkpiano

@davidkpiano davidkpiano commented Nov 7, 2026 •

Copy link
Copy Markdown
Member

Closes two proof gaps from round-10 greenfield trials (project-copilot, fanout-budget).

Coupled child state in predicates

  • With children: "coupled", a canReach predicate and dedupeBy now get a snapshot whose children[id].getSnapshot() returns the child's explored state (grandchildren likewise), not its initial snapshot.
  • A parent's send and the child's receipt count as one state: the predicate is not checked on a step whose sends to coupled children (or child starts) are still undelivered, and in the pump it runs after delivery. So sent === child.n holds on every explored state.

Child usage to the root

  • Decision: yes. A run reports a child machine's request usage to the root (recordUsage → root), so coupled exploration does the same.
  • A coupled child's text request with a usage entry forks once per value. The usage event goes to the root before the child's completion reaches its parent. The root takes or drops it (active, declares @agent.usage, can), as deliverUsageEvent does. It shows on the path as the root receives it.
  • Not listed in vacuous for a child request with no entry (the child can't see whether the root takes usage). "outputs"/"explore" children still deliver none.

Tests

src/verify-coupled.test.ts: predicate sees spawned/invoked child moves, send+receipt atomic, dedupeBy view, child-fed token budget provable, root without usage transition drops it, event shape matches a live runAgent.

pnpm -s check, pnpm -s docs:check, npx vitest run src (1318 passed).


Devin Review

@changeset-bot

changeset-bot Bot commented Nov 7, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 4a0763c

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 6 packages
Name Type
@statelyai/agent Patch
@statelyai/agent-demo Patch
@statelyai/example-next-host Patch
@statelyai/example-tanstack-ai-stream Patch
@statelyai/example-cloudflare-agent-host Patch
@statelyai/example-cloudflare-workers-ai-host Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@coderabbitai

coderabbitai Bot commented Nov 7, 2026

Copy link
Copy Markdown

Warning

Review limit reached

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Next included review available in 1 minute.

Check out review usage here.

View limit details

Limit details: You’ve used all 2 included reviews currently available.

Learn how review limits work.

Review configuration:

Run configuration

  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 558ef6c1-d5c2-401c-8f49-1f41e738ab2b
Commits

Reviewing files that changed from the base of the PR and between 12fab4f and 4a0763c.

Files selected for processing: 4

  • .changeset/coupled-child-proofs.md
  • docs/verify.md
  • src/verify-coupled.test.ts
  • src/verify.ts
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Devin Review found 1 potential issue.

Devin Review

Comment thread src/verify.ts
Comment on lines +1994 to +1997
if (stepping) {
const resolved = resolveStep(prev, id, output);
charges.set(resolved, usage);
return { step: resolved, completed: true };

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔴 Cancelled child requests appear completed

When root usage cancels a child, settleStep has already resolved its request and advanced the child's state. canReach can report a child completion that the live run cancels before delivery.

Learn more

A text request reports usage to the root before its invocation completes in a live run. In coupled exploration, settleStep resolves the child's invoke first, and the move builder records that completion before forwarding usage. If the root leaves the invoking state on usage, the later child completion cannot occur in the live run, but the search has already recorded it and stepped the child. The root can also send the child an event on usage while the search sees it already finished.

Example: A worker's summarize request has an onDone transition to finished. The root's @agent.usage transition leaves the state invoking that worker on a high token count. A live run cancels the worker before summarize completes; coupled exploration records xstate.done.actor(s) and a finished worker before handling that token count.

Recommended fix: Stage each child text completion until its usage event has been delivered at the root. Recheck that the same child and request sessions remain active, then resolve the request and record its completion; discard the staged completion if usage cancels or restarts either actor.

Devin Review


Was this helpful? React with 👍 or 👎 to provide feedback.

@davidkpiano
davidkpiano merged commit d6c41bc into next Nov 7, 2026
4 checks passed
@github-actions github-actions Bot mentioned this pull request Nov 7, 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