Repository navigation
fix(workflow): reject phase() misuse instead of silently running no agents - #283
Merged
Merged
Conversation
…gents phase(title) is a milestone label, but the VM dropped every argument after the title. A script that wrapped its agent calls in a callback passed to phase() ran zero agents and still reported a completed workflow. A lexical pre-run check now rejects phase() calls with more than one argument for inline, scriptPath, and saved scripts, naming the line before a journal or child process exists. The VM throws on the same misuse when the call is not visible statically. A completed run with no agent calls leads its result with a warning. The tool description and system prompt state that phase(title) takes one string and runs nothing.
liuedcson
requested review from
MelodyVAR,
Uking-xxx and
ZouR-Ma
as code owners
October 21, 2026 09:24
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
phase(title)is a milestone label, but the workflow VM dropped every argument after the title. A script that wrapped its agent calls in a callback, as inphase("Review", async () => { await agent(...) }), ran zero agents. The workflow still finished withstatus: "completed"and an empty value. The tool description listedphase()alongside the execution primitives and never gave its signature, so the model reasonably wrote it that way.Changes
features/workflow/script-lint.tsadds a lexical pre-run check, called at the end ofresolveWorkflowScript. It rejects anyphase(...)call with more than one argument and names the line, for exampleWorkflow script line 2: phase(title) takes one string .... It covers inline,scriptPath, and saved scripts, and it runs before a journal or child process exists.obj.phase(...),function phase(...), and method definitions.phaseglobal throws the same message when it receives more than one argument. This catches calls the static check cannot see, such asconst p = phase; p("x", fn).agentCalls === 0gets a warning line at the top of its tool result. This is a warning, not an error: alog()-only script is still valid.agent(),parallel(),pipeline(), anditerate()as the execution primitives, and states thatphase(title)takes one string and runs nothing.docs/orchestration-lifecycle.mddocuments the check, the runtime guard, and the warning.Behavior and compatibility
phasesignature and DSL semantics are unchanged:phase(title): void. Scripts that already used it correctly are unaffected.phase()now fail instead of running nothing. Previously they never did any work.Validation
pnpm run check: passed.packages/coding-agent:pnpm exec vitest --run test/workflow-*.test.ts test/step-system-prompt.test.ts: 8 files and 184 tests passed.test/workflow-script-lint.test.ts)scriptPathrejection with line numbersLimitations
./test.shwas not used as evidence. On the author's machine it fails in unrelated git-dependent suites that also fail onmain.