Summary
In a normal ws-spec-to-pr run using the native structured user-gate, selecting Next at a step transition can leave the workflow state advanced to the next step without dispatching that step.
Observed behavior
Observed in a Cursor session using the native AskQuestion gate and native Task subagent dispatch:
- Step 0 completed successfully.
- The pre-advance validation for Step 1 passed.
- The transition gate returned
Next.
- The orchestrator then stopped after the gate instead of dispatching Step 1.
- Persisted state was:
completedSteps: [0]
currentStep: 1
nextAction: "Run step 1"
stepDispatches contained Step 0 only
pendingGate: null
- A new user message was required to resume execution.
This produces a workflow that looks transitioned in run.json, but Step 1 has not actually started.
Expected behavior
Selecting Next in a native structured transition gate is explicit user confirmation. The orchestrator should continue into the next step dispatch after the tool returns that selection.
If the intended contract is instead to yield the entire turn after every gate, the orchestrator should not leave an apparently advanced state without a persisted pending gate/continuation marker. Resume should be deterministic and automatic from that marker.
Relevant contract ambiguity
ws-shared/gates.md says both:
- Step N+1 must not start without explicit user confirmation.
- Normal execution must halt at the transition gate / one-step-per-turn boundary.
With a blocking native choice tool, the returned selection is already explicit confirmation. The current behavior can interpret the second rule as a stop after the selection while update_state finish has already advanced currentStep.
Reproduction
- Start a normal, non-auto standard
ws-spec-to-pr workflow.
- Complete Step 0.
- Run pre-advance validation for Step 1.
- Present the native transition
user-gate.
- Select Next.
- Inspect state and dispatch telemetry.
- Observe
currentStep: 1 with no Step 1 dispatch event.
Suggested fix
Clarify and enforce one of these state-machine contracts:
- Native gate continuation (preferred): after native
Next, record the gate decision and immediately dispatch Step N+1 in the same orchestrator turn; or
- Turn-yield continuation: persist
pendingGate / continuation state before advancing, and have the next prompt consume it before requiring another user decision.
Add a regression test asserting that a native Next selection cannot leave currentStep advanced with no corresponding next-step dispatch or pending continuation marker.
Summary
In a normal
ws-spec-to-prrun using the native structureduser-gate, selecting Next at a step transition can leave the workflow state advanced to the next step without dispatching that step.Observed behavior
Observed in a Cursor session using the native
AskQuestiongate and nativeTasksubagent dispatch:Next.completedSteps: [0]currentStep: 1nextAction: "Run step 1"stepDispatchescontained Step 0 onlypendingGate: nullThis produces a workflow that looks transitioned in
run.json, but Step 1 has not actually started.Expected behavior
Selecting Next in a native structured transition gate is explicit user confirmation. The orchestrator should continue into the next step dispatch after the tool returns that selection.
If the intended contract is instead to yield the entire turn after every gate, the orchestrator should not leave an apparently advanced state without a persisted pending gate/continuation marker. Resume should be deterministic and automatic from that marker.
Relevant contract ambiguity
ws-shared/gates.mdsays both:With a blocking native choice tool, the returned selection is already explicit confirmation. The current behavior can interpret the second rule as a stop after the selection while
update_state finishhas already advancedcurrentStep.Reproduction
ws-spec-to-prworkflow.user-gate.currentStep: 1with no Step 1 dispatch event.Suggested fix
Clarify and enforce one of these state-machine contracts:
Next, record the gate decision and immediately dispatch Step N+1 in the same orchestrator turn; orpendingGate/ continuation state before advancing, and have the next prompt consume it before requiring another user decision.Add a regression test asserting that a native
Nextselection cannot leavecurrentStepadvanced with no corresponding next-step dispatch or pending continuation marker.