-
Notifications
You must be signed in to change notification settings - Fork 2
plat 295
PLAT-295 — Human-decided branch (route_source: "human") replaces yesno/multiple_choice human_input for new steps
| Coordination | Value |
|---|---|
| Assigned agent | Claude Code |
| Ticket state | implemented locally (new steps only, no migration); tests pass; not deployed |
| Last synchronized | 2026-09-05 |
human_input bundled two concerns: acquiring an answer from outside the
plan (a live person, or a schedule/workshop override) and routing on it
(if_yes_next_step_id / if_no_next_step_id / option_routes). The routing
half duplicated what branch already does, with its own validation, its own
schedule override (human_inputs) alongside route_selections, and its own
canvas/edit UI. Every decision-type use in the workspace (approve/hold,
publish/redraft, skip/continue) is a small fixed choice — exactly a branch
whose selector happens to be a person.
Owner decisions: branch can take the place of human_input for decisions;
human_input stays for free-form value capture (finding-ID lists, a month,
a raw note) because that is not a fork; and existing workflows are not
migrated — only new steps are steered.
-
BranchPlanStep.RouteSource(route_source, only accepted value"human"), exposed throughrouteSwitchStep.GetRouteSource(); routing always returns""— only a branch can ask a person. -
resolveDeterministicRoutingSelectiongained anexecCtxparameter and, for a human-routed branch, hands off toresolveHumanBranchSelection(controller_branch_human.go) after every preseeded source and beforedefault_route_id, so:- caller
route_selections, preseededroute_selection.json,route_source_file,context_dependenciesentry → used, no prompt (schedules answer up front exactly as for any branch); - workshop
execute_step(step_id, human_input=...)→ test answer; - unattended run (
skipHumanInput) →default_route_id, else an actionable error namingroute_selections[step_id]anddefault_route_id; - interactive run →
RequestMultipleChoiceFeedbackwith the routes'route_names as options (sameHumanFeedbackStore, sameBlockingHumanFeedbackUI, same 10-minute wait ashuman_input). Answers resolve fromoption<N>, an index, aroute_name(case-insensitive), aroute_id, or anext_step_id. The blocking call is a swappable package var so the ordering is unit-tested without the store.
- caller
-
validateBranchStepFieldsTypedrejects anyroute_sourceother than""/"human".add_branch_step/update_branch_stepschemas andPartialPlanStepcarry the field; update logs aroute_sourcefield change. -
convert_routing_branch_step_type → routingrejects a human-routed branch. -
Add-time gate on
add_human_input_step(validateNewHumanInputStepIsTextOnly):yesnoandmultiple_choiceare rejected with a message that spells out the equivalentadd_branch_stepcall;textstill works. Add-time only — load, update and execution of existinghuman_inputsteps are untouched. - Canvas:
RoutingStepNodeshows an "asks human" badge whenroute_source === 'human';usePlanToFlow/stepConfigMatchingcarry the field. - Guidance:
branch.md(new "Human-decided branch" section and resolution order),human-input.md(text-only for new steps; decisions → branch),plan-design.mdstep-type table, tool descriptions, canonical workshop prompt.
go build ./... clean; full step_based_workflow package passes with 11 new
tests (branch_human_route_test.go): answer-shape resolution; interactive run
asks with the right question/options and ignores default_route_id; prompt
failure surfaces; unattended run uses default and never prompts; unattended
run without default fails actionably; workshop input wins; human-routed
detection; route_source validation; add_branch_step persists
route_source; add_human_input_step rejects yesno/multiple_choice and keeps
text; convert-to-routing rejected. cmd/server/guidance render test passes.
Frontend tsc reports no errors in the touched files. Not committed, not
deployed, no workflow plan modified.
No migration of existing human_input steps; update_human_input_step is
not gated; HumanInputPlanStep's routing fields remain for existing plans;
no live end-to-end run of a human-routed branch through the real UI yet —
that is the next verification step before deploy.
Auto-synced from docs/ on main. Edit there, not here.