[rig-claude] Improve Claude dynamic-workflow compatibility for rig - #514
Conversation
Promise.all bypasses the shared concurrency limiter, which breaks the Claude dynamic-workflow porting contract. Update the primitive mapping to make the cast approach primary and warn against Promise.all in workflow bodies. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
🧠 Matt Pocock Skills Reviewer has completed the skills-based review. ✅ |
There was a problem hiding this comment.
Skills-Based Review 🧠
Applied /grill-with-docs — approving with one minor suggestion.
📋 Findings
Positive Highlights
- ✅ Fix is correct:
Promise.allgenuinely bypasses the concurrency limiter and thenull-hole failure model — the warning is well-motivated. - ✅ The cast approach is the right recommendation; the reordering makes the safe path obvious.
- ✅ Consistent with the existing table note on
360-parallel-branch-analysis-workflow.md("use instead ofPromise.allwhen porting").
One suggestion (non-blocking)
The Behavior differences section does not yet mention the Promise.all pitfall. A porter who jumps straight to that section could still miss the warning. See inline comment for a suggested bullet.
🧠 Reviewed using Matt Pocock's skills by Matt Pocock Skills Reviewer · sonnet46 25.5 AIC · ⌖ 6.97 AIC · ⊞ 6.3K
Comment /matt to run again
| | `await agent(prompt, { schema })` | `await call.json(prompt, schema, options?)` | `schema` is any `s.*` value (`s.object`, `s.enum`, `s.array`, …); result is typed and validated. Claude workflows only support object schemas; rig accepts any schema type. | | ||
| | Reused prompt + schema pair | `agent({ input, output, instructions })` then `call(worker, input, options?)` | Preferred for anything invoked more than once | | ||
| | `parallel(thunks)` | `parallel(thunks)` | Same barrier semantics; failures become `null` holes. **TypeScript note:** `parallel` uses a single generic `Result` type, so all thunks must return the same type. For agents with different output types, use `Promise.all` (which skips the concurrency limiter) or cast: `parallel<TypeA \| TypeB>([...]) as Promise<[TypeA \| null, TypeB \| null]>`. | | ||
| | `parallel(thunks)` | `parallel(thunks)` | Same barrier semantics; failures become `null` holes. **TypeScript note:** `parallel` uses a single generic `Result` type, so all thunks must return the same type. For agents with different output types, cast to preserve limiter semantics: `parallel<TypeA \| TypeB>([...]) as Promise<[TypeA \| null, TypeB \| null]>`. Avoid `Promise.all` in workflow bodies — it bypasses the concurrency limiter and skips the `null`-hole failure model that `parallel` provides. | |
There was a problem hiding this comment.
[/grill-with-docs] The updated parallel row now warns against Promise.all, but the Behavior differences section — the place porters check before finalising a migration — does not mention this pitfall. A developer skimming that section could still reach for Promise.all for heterogeneous types.
💡 Suggested addition to "Behavior differences"
- **Avoid `Promise.all` in workflow bodies.** `Promise.all` bypasses the shared concurrency limiter and propagates exceptions instead of producing `null` holes. Use `parallel(thunks)` (casting for heterogeneous output types) to match Claude dynamic-workflow semantics.
Compatibility gap addressed
The
parallelprimitive mapping inskills/rig/references/claude-workflow-conversion.mdpreviously recommendedPromise.allas the fallback for heterogeneous agent output types. This is misleading:Promise.allbypasses the shared concurrency limiter and skips thenull-hole failure model thatparallelprovides — both of which are semantically important when porting from Claude dynamic workflows.Why this improves transfer from Claude dynamic workflows to rig
Claude dynamic workflows'
parallel(thunks)always runs inside the limiter. A developer who ports to rig and follows the old guidance (use Promise.all) gets silently different behavior: unlimited concurrency and exceptions propagating instead ofnullholes. The fix makes the cast approach the recommended path and adds an explicit warning aboutPromise.all.Files changed
skills/rig/references/claude-workflow-conversion.md— updated theparallel(thunks)row in the primitive mapping tableValidation
Docs-only change; no code was modified. No additional validation beyond reviewing the edited file for broken links (none found).
Remaining intentional differences
All existing intentional differences documented in the file are preserved. No new differences introduced.