Files
windmill/CONTEXT.md
T
Guilhem LemouelandClaude Opus 5 dda7ab2f30 refactor(chat): give a flow chat turn a module of its own
A turn was not a thing. What one is made of lived in three places — a
reactive status record, a non-reactive runtime map, and locals inside the
function following the job — so the question every piece of a turn's work
has to answer, "am I still the turn this chat is on?", had no owner. Each
await site answered it again from whatever abort flag it had in scope, and
each new await needed another answer; the counter this replaces was the
eighth such answer in as many review rounds.

`Turn` holds the run, the handle that stops it, the cursor its stream
resumes from, the rows it is writing and the timers it armed, and the chat
keys one per conversation. Work carries its turn and passes `isCurrent`
before writing, so a frame buffered before a Stop, a poll dispatched a tick
ago, or a settle that outlived its own turn all land nowhere instead of in
whatever replaced it. Ending a turn is one call rather than an abort, two
timers and a pair of reveals that every caller had to remember, and the
sites that release one say which turn they mean.

The chat itself is keyed on its flow and workspace, so changing flow builds
a new panel rather than re-pointing the old one. That is what makes the
guards removable: nothing survives a flow change to need them.

Fixes found while doing this, each of which the old shape allowed: a
two-minute polling deadline that outlived its turn and stopped the next
one's reading; a run launched into a stopped turn that nothing could name;
a conversation-list refresh on every poll tick of a new chat's first turn;
a failed page walk that freed a chat whose run it never got to ask about;
and a Stop during a launch that tore down the turn that came after it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-16 03:59:48 +02:00

4.5 KiB

Windmill

Open-source platform for internal tools, workflows, API integrations, background jobs and UIs. This file pins the vocabulary that is specific to Windmill's domain, so that code, docs and reviews name the same thing the same way.

Language

Flows

Step: One node of a flow — the unit a user selects in the graph and configures in the right-hand panel. Typed as FlowModule in code. Avoid: module (ambiguous with the architectural sense), node, action

Step setting: A per-step runtime option stored on the step itself: retries, error handling, timeout, concurrency limit, priority, cache, debounce, early stop, skip, suspend, sleep, lifetime. Distinct from the step's inputs and its code. The panel that edits them is the run settings tab; a single setting is still a step setting. Avoid: advanced setting, step config, flow option

Configured: Said of a step setting whose config object is present on the step. Deliberately not the same as "would change the runtime's behaviour" — a setting can be configured and still be a no-op (sleep of 0). Every surface that answers "is this setting on?" answers it this way. Avoid: enabled, active, effective

Trigger step: The first step of a polling flow. It runs on a schedule and returns the items found since its last run; an empty return means there is nothing to process and the flow stops early, marked skipped rather than failed. Avoid: poll script, trigger node, schedule step

Default predicate: The stop_after_if expression seeded onto a trigger step at creation, encoding what "nothing new" looks like. One value, owned in one place, shared by every path that creates a trigger step.

Connect: Arming an input so that the next property picked fills it. A property can be picked from the prop picker or, when the panel is docked beside the graph, by clicking a step node's output. At most one input is armed per panel, so a pick always has exactly one destination. Avoid: link, bind, plug (the icon is a plug; the action is connecting)

Step input: One argument of a step, edited in the step's input form. Its prop picker is a pane beside the form, always visible, so previous results can be browsed without connecting. Avoid: argument field, param

Expression input: Any other place a property can be picked into: the loop iterator, skip and early-stop predicates, the retry condition, a branch predicate, timeout. Its prop picker opens in a popover from the connect button rather than taking a pane. Avoid: JS field, code input

Flow chat

Conversation: One thread of messages against one chat-enabled flow, with its own agent memory. A flow has many; the chat shows one at a time and keeps the others live, so a turn keeps writing while the reader is in another conversation. Avoid: thread, session (that names an AI session, a different thing), chat (that names the surface)

Turn: One question and the answer to it: the run the question started, the handle that stops it, and the rows it is writing. At most one per conversation, and the chat is held for its whole length. A turn exists from the moment it takes the chat — before it has a job, while an attachment uploads or a reload works out whether a run is live — until it is ended. Avoid: request, exchange, message round

Transcript: The rows a conversation's chat holds. Not the conversation: it is the newest page plus whatever older pages the reader has scrolled back through, so a question it cannot answer from what it holds is one to ask the server rather than to guess at. Avoid: history, messages (too easily read as "all of them")

Permissions

Member: A user or group granted a role on a folder, a group, or an item's extra ACL. The list of them is "Members (n)" everywhere it is shown, and one is added with "Add member". Avoid: participant, collaborator, owner, ACL entry, permission (that names the concept, not the people)

Role: The access level a member holds: viewer, writer or admin on a folder; member or admin on a group. Viewers read, writers also edit, admins also manage the members. A group role of manager — manages the group without belonging to it — is a legacy state the UI shows and can leave, but offers no way to enter. Avoid: permission level, access level, rank

Owner: Reserved for the path prefix that says where an item lives — u/alice or f/team. A folder's owners column in the database is its admin members; call those admins, never owners, in the UI. Avoid: using "owner" for a folder admin