Close Claude dynamic-workflow API gaps in rig workflows - #292
Conversation
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
|
🧠 Matt Pocock Skills Reviewer has completed the skills-based review. ✅ |
There was a problem hiding this comment.
🧠 Reviewed using Matt Pocock's skills by Matt Pocock Skills Reviewer · sonnet46 32.2 AIC · ⌖ 4.05 AIC · ⊞ 6.3K
Comment /matt to run again
| return Promise.all(items.map(async (item, index) => { | ||
| let value: unknown = item; | ||
| for (const stage of stages) { | ||
| value = await stage(value, item, index); |
There was a problem hiding this comment.
[/tdd] Pipeline stage exceptions propagate to the caller — unlike call, which swallows errors and returns null, a throwing stage rejects the whole Promise.all for all items. This creates an undocumented failure hole the conversion guide mentions but the implementation doesn't handle.
💡 Suggested test or guard
Add a test that pins the current semantics so the choice is intentional and visible:
it('stage throw rejects the entire pipeline', async () => {
await expect(
pipeline([1, 2, 3], (_prev, item) => {
if (item === 2) throw new Error('boom');
return item;
})
).rejects.toThrow('boom');
});Alternatively, wrap each stage body in try/catch and return null to match call's contract. Either way, callers need a clear signal about which contract this follows.
|
@copilot a rig program exports an agent, it should be internally wrapped into a workflow so that top level phase and other constructs are allowed. |
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Done in fdabea2. The launcher now evaluates the program module and runs its root inside a workflow run ( import { agent, log, phase } from "rig";
phase("Review");
log("reviewing the staged diff");
export default agent({ instructions: "Review the staged diff." });
Covered by new tests in |
|
@copilot resolve the merge conflicts on this branch. |
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Merged
|
Compares the Claude Code dynamic-workflow scripting surface (
export const meta,args,agent(),parallel(),pipeline(),phase(),log(),budget, nestedworkflow(), top-levelreturn) against rig'sworkflow()API, and implements the missing primitives so porting a dynamic workflow is mechanical rather than a redesign.rig already matched
meta/args/parallel/phase/log/return. Six gaps remained:agent(prompt, { schema })call.json(prompt, schema, options?)pipeline(items, ...stages)(previous, item, index){ phase }per callWorkflowCallOptions.phasebudget.total / spent() / remaining()context.budget(metered in agent calls)workflow(ref, args)call.workflow(child, args?, options?)meta.phasesdetails,whenToUsephases: string[], requiredphases?: (string | { title, detail })[],whenToUseRuntime (
skills/rig/rig.ts)call.jsonbuilds a one-off agent constrained to ans.*schema; result typed throughInferSchema,nullon failure likecall.pipelinegains overloads for up to four stages plus a variadic fallback. Items stream independently (no barrier between stages). Single-stagepipeline(items, (item) => ...)is source-compatible.call.workflowruns a child workflow inline on the parent's limiter, agent budget, cancellation signal, and event stream, bracketed bylogevents and restoring the ambient phase.budgetis denominated in agent calls (limits.maxAgents), not tokens — the one deliberate divergence, documented.Docs
references/claude-workflow-conversion.md: primitive mapping, JSON Schema →s.*translation, a worked before/after port, and behavior differences (failure holes, budget units, nesting, sandbox, resume/human gates as non-goals).dynamic-workflows.mdcontext table,SKILL.mddecision rows + reference router,README.mdlinks.310-workflow-audit-verify.md— fan-out/verify workflow in the ported shape.Tests
src/workflow.test.ts: stage threading, per-call phase override, budget metering, nested workflow sharing limits/events, andcall.text+call.jsonagainst a stub engine.Ported shape:
Not ported (Claude Code runtime features, not API surface):
effort,agentType: 'Explore', worktree isolation, resume journals, live human gates. Each is called out in the conversion reference with the rig equivalent.