From ffa5f5c236aba19682297ebba23b3919cea14688 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 19 Aug 2026 08:03:39 +0000 Subject: [PATCH] Fix parallel(thunks) vs Promise.all in samples and docs Clarify that rig's parallel() requires all thunks to return the same TypeScript type (single generic Result), while Claude dynamic workflows accept heterogeneous thunk return types. Three samples (390, 412, 430) were using Promise.all with a comment explaining that parallel() requires uniform thunk types. Add the same clarification to the primitive mapping table in claude-workflow-conversion.md so porters know when to use Promise.all instead. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- skills/rig/references/claude-workflow-conversion.md | 2 +- skills/rig/samples/390-parallel-multi-tool-workflow.md | 6 ++++++ skills/rig/samples/412-parallel-branch-analysis-workflow.md | 1 + skills/rig/samples/430-parallel-git-stats-workflow.md | 1 + 4 files changed, 9 insertions(+), 1 deletion(-) diff --git a/skills/rig/references/claude-workflow-conversion.md b/skills/rig/references/claude-workflow-conversion.md index 46c3ca5..579089a 100644 --- a/skills/rig/references/claude-workflow-conversion.md +++ b/skills/rig/references/claude-workflow-conversion.md @@ -19,7 +19,7 @@ primitives from its context instead of from globals. | `await agent(prompt)` | `await call.text(prompt, options?)` | Returns `string \| null` | | `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 | +| `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([...]) as Promise<[TypeA \| null, TypeB \| null]>`. | | `pipeline(items, ...stages)` | `pipeline(items, ...stages)` | Stages receive `(previous, item, index)`; the first stage's `previous` is the item | | `phase(title)` | `phase(title)` | Same | | `{ phase: "Verify" }` on a call | `{ phase: "Verify" }` in call options | Overrides the ambient phase for that call only | diff --git a/skills/rig/samples/390-parallel-multi-tool-workflow.md b/skills/rig/samples/390-parallel-multi-tool-workflow.md index 474f691..db3e857 100644 --- a/skills/rig/samples/390-parallel-multi-tool-workflow.md +++ b/skills/rig/samples/390-parallel-multi-tool-workflow.md @@ -1,5 +1,10 @@ # 390 - Parallel Multi-Tool Workflow +Uses `parallel(thunks)` — the rig equivalent of `parallel(thunks)` in Claude +dynamic workflows. Respects the shared concurrency limiter and converts failures +to `null` holes. Use it instead of `Promise.all` when porting a Claude dynamic +workflow. + ```rig import { workflow, agent, p, s } from "rig"; @@ -30,6 +35,7 @@ Return categories map and totalVars count.`, }); // Workflow role: Run file count and env health agents in parallel, then combine into an overall health report. +// `parallel(thunks)` requires uniform thunk return types; use `Promise.all` for heterogeneous agents. const parallelMultiToolWorkflow = workflow({ meta: { name: "workspaceHealth", description: "Parallel workspace health analysis", phases: ["Measure", "Rate"] }, body: async ({ call, phase }) => { diff --git a/skills/rig/samples/412-parallel-branch-analysis-workflow.md b/skills/rig/samples/412-parallel-branch-analysis-workflow.md index 866398c..7875e33 100644 --- a/skills/rig/samples/412-parallel-branch-analysis-workflow.md +++ b/skills/rig/samples/412-parallel-branch-analysis-workflow.md @@ -33,6 +33,7 @@ ${p.bash("git log --oneline --since='30 days ago' 2>/dev/null || echo ''")}`, }); // Workflow role: run branch health and commit frequency agents in parallel, then classify overall health. +// `parallel(thunks)` requires uniform thunk return types; use `Promise.all` for heterogeneous agents. const parallelBranchAnalysis = workflow({ meta: { name: "parallelBranchAnalysis", description: "Parallel branch analysis", phases: ["Analyze", "Rate"] }, body: async ({ call, phase }) => { diff --git a/skills/rig/samples/430-parallel-git-stats-workflow.md b/skills/rig/samples/430-parallel-git-stats-workflow.md index 9c5f310..71af9cc 100644 --- a/skills/rig/samples/430-parallel-git-stats-workflow.md +++ b/skills/rig/samples/430-parallel-git-stats-workflow.md @@ -36,6 +36,7 @@ totalFiles = sum of all counts.`, }); // Workflow role: run commit stats and file stats in parallel, then combine results. +// `parallel(thunks)` requires uniform thunk return types; use `Promise.all` for heterogeneous agents. const parallelGitStatsWorkflow = workflow({ meta: { name: "parallel-git-stats", description: "Run commit and file stats in parallel." }, body: async ({ call }) => {