Named types: declare a contract once, refer to it from inputs and outputs
Nobody has claimed this yet.
- Dominant language
- Go
- Stars
- 9
- Forks
- 0
- Avg merge
- 3h 3m
- Merged PRs (30d)
- 509
Description
#621 landed type: enum with a declared values: set, which closes the first slice of #332. It also raises the question that slice deliberately did not answer: an enum's members are declared inline, per input, so two workflows that mean the same thing say it twice, and nothing relates the copies.
inputs:
environment:
type: enum
values: [staging, production]
That is right for one workflow. It is wrong the moment a second one takes the same argument, and wrong again when a called workflow (call:) declares the same input the caller is binding — the two declarations are the same contract written down twice, which is the shape this repository has fixed several times elsewhere and for the same reason.
The question
Is there a first-class way to name a type once and refer to it from inputs: and outputs: — including across files, the way call: already resolves a callee?
Some of the constraints are already decided by things that shipped:
- Resolution is compile-time, and the definition travels.
call:resolves at compile time and carries the callee whole, because a run's specification is frozen at submit and a durable run must not depend on a mutable external definition. A named type has exactly the same requirement: whateverenvironmentmeant when the run was submitted is what it means on its last Continue-As-New segment. - It is a schema type or it is nothing. Types describing the system live in the proto. A reusable declaration is a thing that travels — to the LSP for completion and hover, to
flow docs generate, to the MCP tool schema, to the RPC surface — so it is described by the schema rather than by a hand-written Go struct. - Expansion is bounded by total nodes. A named type referenced from many places is a breadth multiplier, and the house rule is that a diamond is bounded by node count rather than by depth.
- Narrowing a member set is a breaking change.
cmd/flow/breaking.goalready had to learn this for inline enums. A shared definition makes the blast radius of a narrowing larger, not smaller, so the breaking check has to see through the reference to the definition.
What would make it worth doing
The payoff is not brevity. It is that one definition can be checked, documented, completed and diffed — a named type appears once in docs/reference/, an editor can complete its members wherever it is referenced, an MCP tool schema can advertise it, and flow breaking can reason about one contract instead of n copies that drifted.
The cost is a new resolution surface with its own cycles, bounds, diagnostics and failure modes, on a language whose whole style charter (#543) is one obvious spelling.
So this issue is the design question, not a commitment: what is the smallest thing that gives a type a name and a home, without inventing an import system? Options worth writing down before any of them is built — a types: block at workflow level (names, no cross-file resolution), reference by path the way call: does it, or deriving the declaration from a callee's inputs: so the callee is the definition and nothing new is spelled at all.
Follows #332 and #621. Related: #543 (one obvious spelling), #286 and #490 (what a call site may and may not restate).
Generated by Claude Code
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reading the existing enum implementation from #621, the type definitions in the proto, and call: resolution behavior. Then inspect cmd/flow/breaking.go and the mentioned LSP, docs, MCP, and RPC surfaces to map the required resolution and diagnostics. Done means a concrete design records naming, ownership, cross-file resolution, cycles, bounds, and compatibility behavior without committing to an implementation.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- go
- Domain
- api, compilers, developer-experience, documentation
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Needs clarification
- Newbie friendliness
- 25/100