This card takes the built-in node types. Parent #21848 keeps the plugin node types (its PR #21897 adds NodeExecutor.configContract and the approval executor declares it). Raised from #21848's build by domain:services seat 1 (#6021), session_011K3zqE8Pv1Evw5hc8tZCnN. The seat owns it with the parent's domain and priority, and dispatches it once PR #21897 lands.
Blocked-by: #15193
What is measured (#21848's dev, through the dogfood harness at 5fdd32ad):
POST /api/v1/automation with a create_record node whose config.outputVariable is 42 answers 200.
POST /api/v1/automation/:name/trigger then answers 400 FLOW_FAILED: "create_record mk: config does not satisfy the create_record contract — config.outputVariable: Invalid input: expected string, received number".
Mechanism, as the dev read it (verify before acting):
- The built-in executors parse their Zod contract inside
execute (packages/services/service-automation/src/builtin/parse-config.ts) and declare none at registration.
FlowSchema's config refusals check built-ins for presence only.
- So a present built-in value that its contract refuses registers, then fails every run.
Why it is not mechanical: http parses after interpolation, loop parses conditionally, and the region containers' contracts contain their regions. So each built-in needs its own reading of what can be judged at registration.
Done when: each built-in node type whose config can be judged at registration declares its contract through the mechanism PR #21897 adds, a value its contract refuses is refused at registration with the located error, and each built-in that cannot be judged before run time is named, with the reason, in the PR.
Positions: packages/services/service-automation/src/builtin/ (the executors and parse-config.ts).
Generated by Claude Code
This card takes the built-in node types. Parent #21848 keeps the plugin node types (its PR #21897 adds
NodeExecutor.configContractand the approval executor declares it). Raised from #21848's build bydomain:servicesseat 1 (#6021),session_011K3zqE8Pv1Evw5hc8tZCnN. The seat owns it with the parent's domain and priority, and dispatches it once PR #21897 lands.Blocked-by: #15193
What is measured (#21848's dev, through the dogfood harness at
5fdd32ad):POST /api/v1/automationwith acreate_recordnode whoseconfig.outputVariableis42answers200.POST /api/v1/automation/:name/triggerthen answers400 FLOW_FAILED: "create_record mk: config does not satisfy the create_record contract — config.outputVariable: Invalid input: expected string, received number".Mechanism, as the dev read it (verify before acting):
execute(packages/services/service-automation/src/builtin/parse-config.ts) and declare none at registration.FlowSchema's config refusals check built-ins for presence only.Why it is not mechanical:
httpparses after interpolation,loopparses conditionally, and the region containers' contracts contain their regions. So each built-in needs its own reading of what can be judged at registration.Done when: each built-in node type whose config can be judged at registration declares its contract through the mechanism PR #21897 adds, a value its contract refuses is refused at registration with the located error, and each built-in that cannot be judged before run time is named, with the reason, in the PR.
Positions:
packages/services/service-automation/src/builtin/(the executors andparse-config.ts).Generated by Claude Code